aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/util.c')
-rw-r--r--src/firejail/util.c91
1 files changed, 66 insertions, 25 deletions
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}