aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-03-04 09:53:09 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2016-03-04 09:53:09 -0500
commitcb95853d2817e8e6251321c28b4f5f0f35b836a1 (patch)
tree38d5b6d3ff9ec241e56aa82fb1a5d8ee38510dcf
parentcleanup (diff)
downloadfirejail-cb95853d2817e8e6251321c28b4f5f0f35b836a1.tar.gz
firejail-cb95853d2817e8e6251321c28b4f5f0f35b836a1.tar.zst
firejail-cb95853d2817e8e6251321c28b4f5f0f35b836a1.zip
--ls
-rw-r--r--src/firejail/firejail.h4
-rw-r--r--src/firejail/fs_logger.c8
-rw-r--r--src/firejail/ls.c307
-rw-r--r--src/firejail/main.c23
-rw-r--r--src/firejail/util.c1
-rw-r--r--src/lib/pid.c5
6 files changed, 342 insertions, 6 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 87db4d08e..b526b5e00 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -530,5 +530,9 @@ int x11_display(void);
530// return 1 if xpra is installed on the system 530// return 1 if xpra is installed on the system
531int x11_check_xpra(void); 531int x11_check_xpra(void);
532 532
533// ls.c
534void ls_name(const char *name, const char *path);
535void ls(pid_t pid, const char *path);
536
533#endif 537#endif
534 538
diff --git a/src/firejail/fs_logger.c b/src/firejail/fs_logger.c
index 058bcc1c9..227a66cd7 100644
--- a/src/firejail/fs_logger.c
+++ b/src/firejail/fs_logger.c
@@ -157,27 +157,27 @@ void fs_logger_print_log(pid_t pid) {
157 if (uid != 0) { 157 if (uid != 0) {
158 uid_t sandbox_uid = pid_get_uid(pid); 158 uid_t sandbox_uid = pid_get_uid(pid);
159 if (uid != sandbox_uid) { 159 if (uid != sandbox_uid) {
160 fprintf(stderr, "Error: permission denied.\n"); 160 fprintf(stderr, "Error: permission denied\n");
161 exit(1); 161 exit(1);
162 } 162 }
163 } 163 }
164 164
165 // print RUN_FSLOGGER_FILE 165 // print RUN_FSLOGGER_FILE
166 EUID_ROOT();
167 char *fname; 166 char *fname;
168 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_FSLOGGER_FILE) == -1) 167 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_FSLOGGER_FILE) == -1)
169 errExit("asprintf"); 168 errExit("asprintf");
170 169
170 EUID_ROOT();
171 struct stat s; 171 struct stat s;
172 if (stat(fname, &s) == -1) { 172 if (stat(fname, &s) == -1) {
173 printf("Cannot access filesystem log.\n"); 173 fprintf(stderr, "Error: Cannot access filesystem log\n");
174 exit(1); 174 exit(1);
175 } 175 }
176 176
177 /* coverity[toctou] */ 177 /* coverity[toctou] */
178 FILE *fp = fopen(fname, "r"); 178 FILE *fp = fopen(fname, "r");
179 if (!fp) { 179 if (!fp) {
180 printf("Cannot open filesystem log.\n"); 180 fprintf(stderr, "Error: Cannot open filesystem log\n");
181 exit(1); 181 exit(1);
182 } 182 }
183 183
diff --git a/src/firejail/ls.c b/src/firejail/ls.c
new file mode 100644
index 000000000..bd4a4e347
--- /dev/null
+++ b/src/firejail/ls.c
@@ -0,0 +1,307 @@
1/*
2 * Copyright (C) 2014-2016 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20
21#include "firejail.h"
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <dirent.h>
26#include <pwd.h>
27#include <grp.h>
28
29// uid/gid cache
30static uid_t c_uid = 0;
31static char *c_uid_name = NULL;
32static gid_t c_gid = 0;
33static char *g_uid_name = NULL;
34
35static void print_file_or_dir(const char *path, const char *fname, int separator) {
36 assert(fname);
37
38 char *name;
39 if (separator) {
40 if (asprintf(&name, "%s/%s", path, fname) == -1)
41 errExit("asprintf");
42 }
43 else {
44 if (asprintf(&name, "%s%s", path, fname) == -1)
45 errExit("asprintf");
46 }
47
48 struct stat s;
49 int is_broken_link = 0;
50 if (stat(name, &s) == -1) {
51 is_broken_link = 1;
52 if (lstat(name, &s) == -1) {
53 printf("Error: cannot access %s\n", name);
54 return;
55 }
56 }
57
58 // permissions
59 if (S_ISLNK(s.st_mode))
60 printf("l");
61 else if (S_ISDIR(s.st_mode))
62 printf("d");
63 else if (S_ISCHR(s.st_mode))
64 printf("c");
65 else if (S_ISBLK(s.st_mode))
66 printf("b");
67 else if (S_ISSOCK(s.st_mode))
68 printf("s");
69 else
70 printf("-");
71 printf( (s.st_mode & S_IRUSR) ? "r" : "-");
72 printf( (s.st_mode & S_IWUSR) ? "w" : "-");
73 printf( (s.st_mode & S_IXUSR) ? "x" : "-");
74 printf( (s.st_mode & S_IRGRP) ? "r" : "-");
75 printf( (s.st_mode & S_IWGRP) ? "w" : "-");
76 printf( (s.st_mode & S_IXGRP) ? "x" : "-");
77 printf( (s.st_mode & S_IROTH) ? "r" : "-");
78 printf( (s.st_mode & S_IWOTH) ? "w" : "-");
79 printf( (s.st_mode & S_IXOTH) ? "x" : "-");
80 printf(" ");
81
82 // user name
83 char *username;
84 int allocated = 0;
85 if (s.st_uid == 0)
86 username = "root";
87 else if (s.st_uid == c_uid) {
88 assert(c_uid_name);
89 username = c_uid_name;
90 }
91 else {
92 struct passwd *pw = getpwuid(s.st_uid);
93 allocated = 1;
94 if (!pw) {
95 if (asprintf(&username, "%d", s.st_uid) == -1)
96 errExit("asprintf");
97 }
98 else {
99 username = strdup(pw->pw_name);
100 if (!username)
101 errExit("asprintf");
102 }
103
104 if (c_uid == 0) {
105 c_uid = s.st_uid;
106 c_uid_name = strdup(username);
107 if (!c_uid_name)
108 errExit("asprintf");
109 }
110 }
111
112 // print user name, 8 chars maximum
113 int len = strlen(username);
114 if (len > 8) {
115 username[8] = '\0';
116 len = 8;
117 }
118 printf("%s ", username);
119 int i;
120 for (i = len; i < 8; i++)
121 printf(" ");
122 if (allocated)
123 free(username);
124
125
126 // group name
127 char *groupname;
128 allocated = 0;
129 if (s.st_uid == 0)
130 groupname = "root";
131 else {
132 struct group *g = getgrgid(s.st_gid);
133 allocated = 1;
134 if (!g) {
135 if (asprintf(&groupname, "%d", s.st_gid) == -1)
136 errExit("asprintf");
137 }
138 else {
139 groupname = strdup(g->gr_name);
140 if (!groupname)
141 errExit("asprintf");
142 }
143 }
144
145 // print grup name, 8 chars maximum
146 len = strlen(groupname);
147 if (len > 8) {
148 groupname[8] = '\0';
149 len = 8;
150 }
151 printf("%s ", groupname);
152 for (i = len; i < 8; i++)
153 printf(" ");
154 if (allocated)
155 free(groupname);
156
157 char *sz;
158 if (asprintf(&sz, "%d", (int) s.st_size) == -1)
159 errExit("asprintf");
160 printf("%11.10s %s\n", sz, fname);
161 free(sz);
162
163}
164
165static void print_directory(const char *path) {
166 assert(path);
167 struct stat s;
168 if (stat(path, &s) == -1)
169 return;
170 assert(S_ISDIR(s.st_mode));
171
172 DIR *dir;
173 if (!(dir = opendir(path))) {
174 // sleep 2 seconds and try again
175 sleep(2);
176 if (!(dir = opendir(path))) {
177 fprintf(stderr, "Error: cannot open directory %s\n", path);
178 exit(1);
179 }
180 }
181
182 struct dirent *entry;
183 while ((entry = readdir(dir))) {
184 if (strcmp(entry->d_name, ".") == 0)
185 continue;
186 if (strcmp(entry->d_name, "..") == 0)
187 continue;
188
189 print_file_or_dir(path, entry->d_name, 0);
190 }
191
192 closedir(dir);
193}
194
195void ls_name(const char *name, const char *path) {
196 EUID_ASSERT();
197
198 if (!name || strlen(name) == 0) {
199 fprintf(stderr, "Error: invalid sandbox name\n");
200 exit(1);
201 }
202 pid_t pid;
203 if (name2pid(name, &pid)) {
204 fprintf(stderr, "Error: cannot find sandbox %s\n", name);
205 exit(1);
206 }
207
208 ls(pid, path);
209}
210
211void ls(pid_t pid, const char *path) {
212 EUID_ASSERT();
213
214 // if the pid is that of a firejail process, use the pid of the first child process
215 char *comm = pid_proc_comm(pid);
216 if (comm) {
217 if (strcmp(comm, "firejail") == 0) {
218 pid_t child;
219 if (find_child(pid, &child) == 0) {
220 pid = child;
221 }
222 }
223 free(comm);
224 }
225
226 // check privileges for non-root users
227 uid_t uid = getuid();
228 if (uid != 0) {
229 uid_t sandbox_uid = pid_get_uid(pid);
230 if (uid != sandbox_uid) {
231 fprintf(stderr, "Error: permission denied.\n");
232 exit(1);
233 }
234 }
235
236 EUID_ROOT();
237 // chroot
238 char *rootdir;
239 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
240 errExit("asprintf");
241 if (chroot(rootdir) < 0)
242 errExit("chroot");
243 if (chdir("/") < 0)
244 errExit("chdir");
245
246 // full path or file in current directory?
247 char *fname;
248 if (*path == '/') {
249 fname = strdup(path);
250 if (!fname)
251 errExit("strdup");
252 }
253 else if (*path == '~') {
254 if (asprintf(&fname, "%s%s", cfg.homedir, path + 1) == -1)
255 errExit("asprintf");
256 }
257 else {
258 fprintf(stderr, "Error: Cannot access file %s\n", path);
259 exit(1);
260 }
261
262 // list directory contents
263 struct stat s;
264 if (stat(fname, &s) == -1) {
265 fprintf(stderr, "Error: Cannot access file %s\n", fname);
266 exit(1);
267 }
268 if (S_ISDIR(s.st_mode)) {
269 char *rp = realpath(fname, NULL);
270 if (!rp) {
271 fprintf(stderr, "Error: Cannot access file %s\n", fname);
272 exit(1);
273 }
274 if (arg_debug)
275 printf("realpath %s\n", rp);
276
277 char *dir;
278 if (asprintf(&dir, "%s/", rp) == -1)
279 errExit("asprintf");
280
281 print_directory(dir);
282 free(rp);
283 free(dir);
284 }
285 else {
286 char *rp = realpath(fname, NULL);
287 if (!rp) {
288 fprintf(stderr, "Error: Cannot access file %s\n", fname);
289 exit(1);
290 }
291 if (arg_debug)
292 printf("realpath %s\n", rp);
293 char *split = strrchr(rp, '/');
294 if (split) {
295 *split = '\0';
296 char *rp2 = split + 1;
297 if (arg_debug)
298 printf("path %s, file %s\n", rp, rp2);
299 print_file_or_dir(rp, rp2, 1);
300 }
301 free(rp);
302 }
303
304 free(fname);
305
306 exit(0);
307}
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 925cd3022..68606a313 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -426,6 +426,29 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
426 exit(0); 426 exit(0);
427 } 427 }
428#endif 428#endif
429 else if (strncmp(argv[i], "--ls=", 5) == 0) {
430 logargs(argc, argv);
431
432 // verify path
433 if ((i + 2) != argc) {
434 fprintf(stderr, "Error: invalid --ls option, path expected\n");
435 exit(1);
436 }
437 char *path = argv[i + 1];
438 invalid_filename(path);
439 if (strstr(path, "..")) {
440 fprintf(stderr, "Error: invalid file name %s\n", path);
441 exit(1);
442 }
443
444 // list directory contents
445 pid_t pid;
446 if (read_pid(argv[i] + 5, &pid) == 0)
447 ls(pid, path);
448 else
449 ls_name(argv[i] + 5, path);
450 exit(0);
451 }
429 else if (strncmp(argv[i], "--join=", 7) == 0) { 452 else if (strncmp(argv[i], "--join=", 7) == 0) {
430 logargs(argc, argv); 453 logargs(argc, argv);
431 454
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 3463095f9..5c5e7d9e8 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -566,6 +566,7 @@ const char *gnu_basename(const char *path) {
566uid_t pid_get_uid(pid_t pid) { 566uid_t pid_get_uid(pid_t pid) {
567 EUID_ASSERT(); 567 EUID_ASSERT();
568 uid_t rv = 0; 568 uid_t rv = 0;
569printf("here %d, pid %d\n", __LINE__, pid);
569 570
570 // open status file 571 // open status file
571 char *file; 572 char *file;
diff --git a/src/lib/pid.c b/src/lib/pid.c
index 6251f8b61..a89ac434b 100644
--- a/src/lib/pid.c
+++ b/src/lib/pid.c
@@ -136,13 +136,14 @@ char *pid_get_user_name(uid_t uid) {
136 136
137uid_t pid_get_uid(pid_t pid) { 137uid_t pid_get_uid(pid_t pid) {
138 uid_t rv = 0; 138 uid_t rv = 0;
139 139
140 // open statua file 140 // open status file
141 char *file; 141 char *file;
142 if (asprintf(&file, "/proc/%u/status", pid) == -1) { 142 if (asprintf(&file, "/proc/%u/status", pid) == -1) {
143 perror("asprintf"); 143 perror("asprintf");
144 exit(1); 144 exit(1);
145 } 145 }
146
146 FILE *fp = fopen(file, "r"); 147 FILE *fp = fopen(file, "r");
147 if (!fp) { 148 if (!fp) {
148 free(file); 149 free(file);