aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/ls.c
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2020-08-19 00:39:20 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2020-08-19 00:39:20 +0200
commit66c398e34cdf39c5ad9aa06bd022ce8a518bcbc4 (patch)
tree7125ce2753038d99482ecb34f330630fe5fc72d0 /src/firejail/ls.c
parentfirejail: don't pass command line through shell when redirecting output (diff)
downloadfirejail-66c398e34cdf39c5ad9aa06bd022ce8a518bcbc4.tar.gz
firejail-66c398e34cdf39c5ad9aa06bd022ce8a518bcbc4.tar.zst
firejail-66c398e34cdf39c5ad9aa06bd022ce8a518bcbc4.zip
refactor ls.c and prepare for new --cat option
Diffstat (limited to 'src/firejail/ls.c')
-rw-r--r--src/firejail/ls.c163
1 files changed, 100 insertions, 63 deletions
diff --git a/src/firejail/ls.c b/src/firejail/ls.c
index aa33d838b..7c7f8b75f 100644
--- a/src/firejail/ls.c
+++ b/src/firejail/ls.c
@@ -34,18 +34,12 @@
34static uid_t c_uid = 0; 34static uid_t c_uid = 0;
35static char *c_uid_name = NULL; 35static char *c_uid_name = NULL;
36 36
37static void print_file_or_dir(const char *path, const char *fname, int separator) { 37static void print_file_or_dir(const char *path, const char *fname) {
38 assert(fname); 38 assert(fname);
39 39
40 char *name; 40 char *name;
41 if (separator) { 41 if (asprintf(&name, "%s/%s", path, fname) == -1)
42 if (asprintf(&name, "%s/%s", path, fname) == -1) 42 errExit("asprintf");
43 errExit("asprintf");
44 }
45 else {
46 if (asprintf(&name, "%s%s", path, fname) == -1)
47 errExit("asprintf");
48 }
49 43
50 struct stat s; 44 struct stat s;
51 if (stat(name, &s) == -1) { 45 if (stat(name, &s) == -1) {
@@ -178,13 +172,75 @@ static void print_directory(const char *path) {
178 errExit("scandir"); 172 errExit("scandir");
179 else { 173 else {
180 for (i = 0; i < n; i++) { 174 for (i = 0; i < n; i++) {
181 print_file_or_dir(path, namelist[i]->d_name, 0); 175 print_file_or_dir(path, namelist[i]->d_name);
182 free(namelist[i]); 176 free(namelist[i]);
183 } 177 }
184 } 178 }
185 free(namelist); 179 free(namelist);
186} 180}
187 181
182void ls(const char *path) {
183 EUID_ASSERT();
184 assert(path);
185
186 char *rp = realpath(path, NULL);
187 if (!rp || access(rp, R_OK) == -1) {
188 fprintf(stderr, "Error: cannot access %s\n", path);
189 exit(1);
190 }
191 if (arg_debug)
192 printf("ls %s\n", rp);
193
194 // list directory contents
195 struct stat s;
196 if (stat(rp, &s) == -1) {
197 fprintf(stderr, "Error: cannot access %s\n", rp);
198 exit(1);
199 }
200 if (S_ISDIR(s.st_mode))
201 print_directory(rp);
202 else {
203 char *split = strrchr(rp, '/');
204 if (split) {
205 *split = '\0';
206 char *rp2 = split + 1;
207 if (arg_debug)
208 printf("path %s, file %s\n", rp, rp2);
209 print_file_or_dir(rp, rp2);
210 }
211 }
212 free(rp);
213}
214
215void cat(const char *path) {
216 EUID_ASSERT();
217 assert(path);
218
219 if (arg_debug)
220 printf("cat %s\n", path);
221 FILE *fp = fopen(path, "r");
222 if (!fp) {
223 fprintf(stderr, "Error: cannot read %s\n", path);
224 exit(1);
225 }
226 int fd = fileno(fp);
227 if (fd == -1)
228 errExit("fileno");
229 struct stat s;
230 if (fstat(fd, &s) == -1)
231 errExit("fstat");
232 if (!S_ISREG(s.st_mode)) {
233 fprintf(stderr, "Error: %s is not a regular file\n", path);
234 exit(1);
235 }
236
237 int c;
238 while ((c = fgetc(fp)) != EOF)
239 fputc(c, stdout);
240 fflush(stdout);
241 fclose(fp);
242}
243
188char *expand_path(const char *path) { 244char *expand_path(const char *path) {
189 char *fname = NULL; 245 char *fname = NULL;
190 if (*path == '/') { 246 if (*path == '/') {
@@ -219,14 +275,14 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
219 check_join_permission(pid); 275 check_join_permission(pid);
220 276
221 // expand paths 277 // expand paths
222 char *fname1 = expand_path(path1);; 278 char *fname1 = expand_path(path1);
223 char *fname2 = NULL; 279 char *fname2 = NULL;
224 if (path2 != NULL) { 280 if (path2 != NULL) {
225 fname2 = expand_path(path2); 281 fname2 = expand_path(path2);
226 } 282 }
227 if (arg_debug) { 283 if (arg_debug) {
228 printf("file1 %s\n", fname1); 284 printf("file1 %s\n", fname1);
229 printf("file2 %s\n", fname2); 285 printf("file2 %s\n", fname2 ? fname2 : "(null)");
230 } 286 }
231 287
232 // sandbox root directory 288 // sandbox root directory
@@ -234,57 +290,36 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
234 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) 290 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
235 errExit("asprintf"); 291 errExit("asprintf");
236 292
237 if (op == SANDBOX_FS_LS) { 293 if (op == SANDBOX_FS_LS || op == SANDBOX_FS_CAT) {
238 EUID_ROOT(); 294 pid_t child = fork();
239 // chroot 295 if (child < 0)
240 if (chroot(rootdir) < 0) 296 errExit("fork");
241 errExit("chroot"); 297 if (child == 0) {
242 if (chdir("/") < 0) 298 EUID_ROOT();
243 errExit("chdir"); 299 // chroot
244 300 if (chroot(rootdir) < 0)
245 // drop privileges 301 errExit("chroot");
246 drop_privs(0); 302 if (chdir("/") < 0)
247 303 errExit("chdir");
248 // check access
249 if (access(fname1, R_OK) == -1) {
250 fprintf(stderr, "Error: Cannot access %s\n", fname1);
251 exit(1);
252 }
253 /* coverity[toctou] */
254 char *rp = realpath(fname1, NULL);
255 if (!rp) {
256 fprintf(stderr, "Error: Cannot access %s\n", fname1);
257 exit(1);
258 }
259 if (arg_debug)
260 printf("realpath %s\n", rp);
261
262 304
263 // list directory contents 305 // drop privileges
264 struct stat s; 306 drop_privs(0);
265 if (stat(rp, &s) == -1) {
266 fprintf(stderr, "Error: Cannot access %s\n", rp);
267 exit(1);
268 }
269 if (S_ISDIR(s.st_mode)) {
270 char *dir;
271 if (asprintf(&dir, "%s/", rp) == -1)
272 errExit("asprintf");
273 307
274 print_directory(dir); 308 if (op == SANDBOX_FS_LS)
275 free(dir); 309 ls(fname1);
276 } 310 else
277 else { 311 cat(fname1);
278 char *split = strrchr(rp, '/'); 312#ifdef HAVE_GCOV
279 if (split) { 313 __gcov_flush();
280 *split = '\0'; 314#endif
281 char *rp2 = split + 1; 315 _exit(0);
282 if (arg_debug)
283 printf("path %s, file %s\n", rp, rp2);
284 print_file_or_dir(rp, rp2, 1);
285 }
286 } 316 }
287 free(rp); 317 // wait for the child to finish
318 int status = 0;
319 waitpid(child, &status, 0);
320 if (WIFEXITED(status) && WEXITSTATUS(status) == 0);
321 else
322 exit(1);
288 } 323 }
289 324
290 // get file from sandbox and store it in the current directory 325 // get file from sandbox and store it in the current directory
@@ -303,10 +338,12 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
303 // create a user-owned temporary file in /run/firejail directory 338 // create a user-owned temporary file in /run/firejail directory
304 char tmp_fname[] = "/run/firejail/tmpget-XXXXXX"; 339 char tmp_fname[] = "/run/firejail/tmpget-XXXXXX";
305 int fd = mkstemp(tmp_fname); 340 int fd = mkstemp(tmp_fname);
306 if (fd != -1) { 341 if (fd == -1) {
307 SET_PERMS_FD(fd, getuid(), getgid(), 0600); 342 fprintf(stderr, "Error: cannot create temporary file %s\n", tmp_fname);
308 close(fd); 343 exit(1);
309 } 344 }
345 SET_PERMS_FD(fd, getuid(), getgid(), 0600);
346 close(fd);
310 347
311 // copy the source file into the temporary file - we need to chroot 348 // copy the source file into the temporary file - we need to chroot
312 pid_t child = fork(); 349 pid_t child = fork();