aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2017-01-29 15:00:21 -0500
committerLibravatar GitHub <noreply@github.com>2017-01-29 15:00:21 -0500
commitca0199027768def4e83ba785752a1b77b68b8c64 (patch)
tree28c099109c594d49f455be3cd437ff2bc780b651
parentsupport allow-private-blacklist in profile files (diff)
parentfixing --hosts-file privelege check (diff)
downloadfirejail-ca0199027768def4e83ba785752a1b77b68b8c64.tar.gz
firejail-ca0199027768def4e83ba785752a1b77b68b8c64.tar.zst
firejail-ca0199027768def4e83ba785752a1b77b68b8c64.zip
Merge pull request #1079 from ibukanov/copy_to_root_fix
fixing --hosts-file privelege check
-rw-r--r--src/firejail/firejail.h1
-rw-r--r--src/firejail/fs_hostname.c2
-rw-r--r--src/firejail/util.c91
3 files changed, 68 insertions, 26 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 0f836f1db..7d6e16094 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -453,6 +453,7 @@ void logargs(int argc, char **argv) ;
453void logerr(const char *msg); 453void logerr(const char *msg);
454int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); 454int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
455void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); 455void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
456void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
456void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode); 457void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode);
457int is_dir(const char *fname); 458int is_dir(const char *fname);
458int is_link(const char *fname); 459int is_link(const char *fname);
diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c
index 19af11dd8..3b586b276 100644
--- a/src/firejail/fs_hostname.c
+++ b/src/firejail/fs_hostname.c
@@ -147,7 +147,7 @@ errexit:
147} 147}
148 148
149void fs_store_hosts_file(void) { 149void fs_store_hosts_file(void) {
150 copy_file(cfg.hosts_file, RUN_HOSTS_FILE, 0, 0, 0644); // root needed 150 copy_file_from_user_to_root(cfg.hosts_file, RUN_HOSTS_FILE, 0, 0, 0644); // root needed
151} 151}
152 152
153void fs_mount_hosts_file(void) { 153void fs_mount_hosts_file(void) {
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 10000e912..44891ce2d 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -169,6 +169,25 @@ void logerr(const char *msg) {
169 closelog(); 169 closelog();
170} 170}
171 171
172static int copy_file_by_fd(int src, int dst) {
173 assert(src >= 0);
174 assert(dst >= 0);
175
176 ssize_t len;
177 static const int BUFLEN = 1024;
178 unsigned char buf[BUFLEN];
179 while ((len = read(src, buf, BUFLEN)) > 0) {
180 int done = 0;
181 while (done != len) {
182 int rv = write(dst, buf + done, len - done);
183 if (rv == -1)
184 return -1;
185 done += rv;
186 }
187 }
188 fflush(0);
189 return 0;
190}
172 191
173// return -1 if error, 0 if no error; if destname already exists, return error 192// return -1 if error, 0 if no error; if destname already exists, return error
174int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) { 193int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) {
@@ -190,33 +209,16 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m
190 return -1; 209 return -1;
191 } 210 }
192 211
193 // copy 212 int errors = copy_file_by_fd(src, dst);
194 ssize_t len; 213 if (!errors) {
195 static const int BUFLEN = 1024; 214 if (fchown(dst, uid, gid) == -1)
196 unsigned char buf[BUFLEN]; 215 errExit("fchown");
197 while ((len = read(src, buf, BUFLEN)) > 0) { 216 if (fchmod(dst, mode) == -1)
198 int done = 0; 217 errExit("fchmod");
199 while (done != len) {
200 int rv = write(dst, buf + done, len - done);
201 if (rv == -1) {
202 close(src);
203 close(dst);
204 return -1;
205 }
206
207 done += rv;
208 }
209 } 218 }
210 fflush(0);
211
212 if (fchown(dst, uid, gid) == -1)
213 errExit("fchown");
214 if (fchmod(dst, mode) == -1)
215 errExit("fchmod");
216
217 close(src); 219 close(src);
218 close(dst); 220 close(dst);
219 return 0; 221 return errors;
220} 222}
221 223
222// return -1 if error, 0 if no error 224// return -1 if error, 0 if no error
@@ -241,6 +243,45 @@ void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid
241 waitpid(child, NULL, 0); 243 waitpid(child, NULL, 0);
242} 244}
243 245
246void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) {
247 // open destination
248 int dst = open(destname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
249 if (dst < 0) {
250 fprintf(stderr, "Warning: cannot open destination file %s, file not copied\n", destname);
251 return;
252 }
253
254 pid_t child = fork();
255 if (child < 0)
256 errExit("fork");
257 if (child == 0) {
258 // drop privileges
259 drop_privs(0);
260
261 int src = open(srcname, O_RDONLY);
262 if (src < 0) {
263 fprintf(stderr, "Warning: cannot open source file %s, file not copied\n", srcname);
264 } else {
265 if (copy_file_by_fd(src, dst)) {
266 fprintf(stderr, "Warning: cannot copy %s\n", srcname);
267 }
268 close(src);
269 }
270 close(dst);
271#ifdef HAVE_GCOV
272 __gcov_flush();
273#endif
274 _exit(0);
275 }
276 // wait for the child to finish
277 waitpid(child, NULL, 0);
278 if (fchown(dst, uid, gid) == -1)
279 errExit("fchown");
280 if (fchmod(dst, mode) == -1)
281 errExit("fchmod");
282 close(dst);
283}
284
244// return -1 if error, 0 if no error 285// return -1 if error, 0 if no error
245void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode) { 286void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode) {
246 pid_t child = fork(); 287 pid_t child = fork();
@@ -864,4 +905,4 @@ errexit:
864 close(fd); 905 close(fd);
865 fprintf(stderr, "Error: cannot read %s\n", fname); 906 fprintf(stderr, "Error: cannot read %s\n", fname);
866 exit(1); 907 exit(1);
867} \ No newline at end of file 908}