diff options
-rw-r--r-- | Makefile.in | 10 | ||||
-rw-r--r-- | src/firejail/restrict_users.c | 14 | ||||
-rw-r--r-- | src/include/firejail_user.h | 2 | ||||
-rw-r--r-- | src/lib/firejail_user.c | 66 |
4 files changed, 79 insertions, 13 deletions
diff --git a/Makefile.in b/Makefile.in index fef544267..cbcf252df 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -22,16 +22,14 @@ HAVE_CONTRIB_INSTALL=@HAVE_CONTRIB_INSTALL@ | |||
22 | BUSYBOX_WORKAROUND=@BUSYBOX_WORKAROUND@ | 22 | BUSYBOX_WORKAROUND=@BUSYBOX_WORKAROUND@ |
23 | HAVE_SUID=@HAVE_SUID@ | 23 | HAVE_SUID=@HAVE_SUID@ |
24 | 24 | ||
25 | uids.h:; ./mkuid.sh | ||
26 | |||
27 | .PHONY: mylibs $(MYLIBS) | 25 | .PHONY: mylibs $(MYLIBS) |
28 | mylibs: $(MYLIBS) | 26 | mylibs: $(MYLIBS) |
29 | $(MYLIBS): uids.h | 27 | $(MYLIBS): |
30 | $(MAKE) -C $@ | 28 | $(MAKE) -C $@ |
31 | 29 | ||
32 | .PHONY: apps $(APPS) | 30 | .PHONY: apps $(APPS) |
33 | apps: $(APPS) | 31 | apps: $(APPS) |
34 | $(APPS): $(MYLIBS) uids.h | 32 | $(APPS): $(MYLIBS) |
35 | $(MAKE) -C $@ | 33 | $(MAKE) -C $@ |
36 | 34 | ||
37 | $(MANPAGES): $(wildcard src/man/*.txt) | 35 | $(MANPAGES): $(wildcard src/man/*.txt) |
@@ -73,7 +71,7 @@ distclean: clean | |||
73 | for dir in $(APPS) $(MYLIBS); do \ | 71 | for dir in $(APPS) $(MYLIBS); do \ |
74 | $(MAKE) -C $$dir distclean; \ | 72 | $(MAKE) -C $$dir distclean; \ |
75 | done | 73 | done |
76 | rm -fr Makefile autom4te.cache config.log config.status config.h uids.h dummy.o src/common.mk | 74 | rm -fr Makefile autom4te.cache config.log config.status config.h dummy.o src/common.mk |
77 | 75 | ||
78 | realinstall: | 76 | realinstall: |
79 | # firejail executable | 77 | # firejail executable |
@@ -192,7 +190,7 @@ uninstall: | |||
192 | rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firemon | 190 | rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firemon |
193 | rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg | 191 | rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg |
194 | 192 | ||
195 | DISTFILES = "src etc platform contrib configure configure.ac dummy.c Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh mkuid.sh COPYING README RELNOTES" | 193 | DISTFILES = "src etc platform contrib configure configure.ac dummy.c Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh COPYING README RELNOTES" |
196 | DISTFILES_TEST = "test/apps test/apps-x11 test/apps-x11-xorg test/root test/fcopy test/environment test/profiles test/utils test/compile test/filters test/network test/arguments test/fs test/sysutils test/chroot" | 194 | DISTFILES_TEST = "test/apps test/apps-x11 test/apps-x11-xorg test/root test/fcopy test/environment test/profiles test/utils test/compile test/filters test/network test/arguments test/fs test/sysutils test/chroot" |
197 | 195 | ||
198 | dist: | 196 | dist: |
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c index 982dba5ac..d66deeb97 100644 --- a/src/firejail/restrict_users.c +++ b/src/firejail/restrict_users.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include "../include/firejail_user.h" | ||
21 | #include <sys/mount.h> | 22 | #include <sys/mount.h> |
22 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
23 | #include <linux/limits.h> | 24 | #include <linux/limits.h> |
@@ -26,7 +27,6 @@ | |||
26 | #include <dirent.h> | 27 | #include <dirent.h> |
27 | #include <fcntl.h> | 28 | #include <fcntl.h> |
28 | #include <errno.h> | 29 | #include <errno.h> |
29 | #include "../../uids.h" | ||
30 | 30 | ||
31 | #define MAXBUF 1024 | 31 | #define MAXBUF 1024 |
32 | 32 | ||
@@ -115,8 +115,9 @@ static void sanitize_passwd(void) { | |||
115 | struct stat s; | 115 | struct stat s; |
116 | if (stat("/etc/passwd", &s) == -1) | 116 | if (stat("/etc/passwd", &s) == -1) |
117 | return; | 117 | return; |
118 | assert(uid_min); | ||
118 | if (arg_debug) | 119 | if (arg_debug) |
119 | printf("Sanitizing /etc/passwd, UID_MIN %d\n", UID_MIN); | 120 | printf("Sanitizing /etc/passwd, UID_MIN %d\n", uid_min); |
120 | if (is_link("/etc/passwd")) { | 121 | if (is_link("/etc/passwd")) { |
121 | fprintf(stderr, "Error: invalid /etc/passwd\n"); | 122 | fprintf(stderr, "Error: invalid /etc/passwd\n"); |
122 | exit(1); | 123 | exit(1); |
@@ -167,7 +168,8 @@ static void sanitize_passwd(void) { | |||
167 | int rv = sscanf(ptr, "%d:", &uid); | 168 | int rv = sscanf(ptr, "%d:", &uid); |
168 | if (rv == 0 || uid < 0) | 169 | if (rv == 0 || uid < 0) |
169 | goto errout; | 170 | goto errout; |
170 | if (uid < UID_MIN || uid == 65534) { // on Debian platforms user nobody is 65534 | 171 | assert(uid_min); |
172 | if (uid < uid_min || uid == 65534) { // on Debian platforms user nobody is 65534 | ||
171 | fprintf(fpout, "%s", buf); | 173 | fprintf(fpout, "%s", buf); |
172 | continue; | 174 | continue; |
173 | } | 175 | } |
@@ -248,8 +250,9 @@ static void sanitize_group(void) { | |||
248 | struct stat s; | 250 | struct stat s; |
249 | if (stat("/etc/group", &s) == -1) | 251 | if (stat("/etc/group", &s) == -1) |
250 | return; | 252 | return; |
253 | assert(gid_min); | ||
251 | if (arg_debug) | 254 | if (arg_debug) |
252 | printf("Sanitizing /etc/group, GID_MIN %d\n", GID_MIN); | 255 | printf("Sanitizing /etc/group, GID_MIN %d\n", gid_min); |
253 | if (is_link("/etc/group")) { | 256 | if (is_link("/etc/group")) { |
254 | fprintf(stderr, "Error: invalid /etc/group\n"); | 257 | fprintf(stderr, "Error: invalid /etc/group\n"); |
255 | exit(1); | 258 | exit(1); |
@@ -299,7 +302,8 @@ static void sanitize_group(void) { | |||
299 | int rv = sscanf(ptr, "%d:", &gid); | 302 | int rv = sscanf(ptr, "%d:", &gid); |
300 | if (rv == 0 || gid < 0) | 303 | if (rv == 0 || gid < 0) |
301 | goto errout; | 304 | goto errout; |
302 | if (gid < GID_MIN || gid == 65534) { // on Debian platforms 65534 is group nogroup | 305 | assert(gid_min); |
306 | if (gid < gid_min || gid == 65534) { // on Debian platforms 65534 is group nogroup | ||
303 | if (copy_line(fpout, buf, ptr)) | 307 | if (copy_line(fpout, buf, ptr)) |
304 | goto errout; | 308 | goto errout; |
305 | continue; | 309 | continue; |
diff --git a/src/include/firejail_user.h b/src/include/firejail_user.h index a7d30225e..66e618fbe 100644 --- a/src/include/firejail_user.h +++ b/src/include/firejail_user.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #ifndef FIREJAIL_USER_H | 20 | #ifndef FIREJAIL_USER_H |
21 | #define FIREJAIL_USER_H | 21 | #define FIREJAIL_USER_H |
22 | 22 | ||
23 | extern int uid_min; | ||
24 | extern int gid_min; | ||
23 | 25 | ||
24 | // returns 1 if the user is found in the database or if the database was not created | 26 | // returns 1 if the user is found in the database or if the database was not created |
25 | int firejail_user_check(const char *name); | 27 | int firejail_user_check(const char *name); |
diff --git a/src/lib/firejail_user.c b/src/lib/firejail_user.c index 0cc0ac6c1..c7af14254 100644 --- a/src/lib/firejail_user.c +++ b/src/lib/firejail_user.c | |||
@@ -26,11 +26,70 @@ | |||
26 | // One username per line in the file | 26 | // One username per line in the file |
27 | 27 | ||
28 | #include "../include/common.h" | 28 | #include "../include/common.h" |
29 | #include "../include/firejail_user.h" | ||
29 | #include <sys/types.h> | 30 | #include <sys/types.h> |
30 | #include <pwd.h> | 31 | #include <pwd.h> |
31 | #include "../../uids.h" | ||
32 | 32 | ||
33 | #define MAXBUF 4098 | 33 | #define MAXBUF 4098 |
34 | |||
35 | // minimum values for uid and gid extracted from /etc/login.defs | ||
36 | int uid_min = 0; | ||
37 | int gid_min = 0; | ||
38 | |||
39 | static void init_uid_gid_min(void) { | ||
40 | if (uid_min != 0 && gid_min != 0) | ||
41 | return; | ||
42 | |||
43 | // read the real values from login.def | ||
44 | FILE *fp = fopen("/etc/login.defs", "r"); | ||
45 | if (!fp) | ||
46 | goto errexit; | ||
47 | |||
48 | char buf[MAXBUF]; | ||
49 | while (fgets(buf, MAXBUF, fp)) { | ||
50 | // comments | ||
51 | if (*buf == '#') | ||
52 | continue; | ||
53 | // skip empty space | ||
54 | char *ptr = buf; | ||
55 | while (*ptr == ' ' || *ptr == '\t') | ||
56 | ptr++; | ||
57 | |||
58 | if (strncmp(ptr, "UID_MIN", 7) == 0) { | ||
59 | int rv = sscanf(ptr + 7, "%d", &uid_min); | ||
60 | if (rv != 1 || uid_min < 0) { | ||
61 | fclose(fp); | ||
62 | goto errexit; | ||
63 | } | ||
64 | } | ||
65 | else if (strncmp(ptr, "GID_MIN", 7) == 0) { | ||
66 | int rv = sscanf(ptr + 7, "%d", &gid_min); | ||
67 | if (rv != 1 || gid_min < 0) { | ||
68 | fclose(fp); | ||
69 | goto errexit; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | if (uid_min != 0 && gid_min != 0) | ||
74 | break; | ||
75 | |||
76 | } | ||
77 | fclose(fp); | ||
78 | |||
79 | if (uid_min == 0 || gid_min == 0) | ||
80 | goto errexit; | ||
81 | //printf("uid_min %d, gid_min %d\n", uid_min, gid_min); | ||
82 | |||
83 | return; | ||
84 | |||
85 | errexit: | ||
86 | fprintf(stderr, "Error: cannot read UID_MIN and/or GID_MIN from /etc/login.defs, using 1000 by default\n"); | ||
87 | uid_min = 1000; | ||
88 | gid_min = 1000; | ||
89 | } | ||
90 | |||
91 | |||
92 | |||
34 | static inline char *get_fname(void) { | 93 | static inline char *get_fname(void) { |
35 | char *fname; | 94 | char *fname; |
36 | if (asprintf(&fname, "%s/firejail.users", SYSCONFDIR) == -1) | 95 | if (asprintf(&fname, "%s/firejail.users", SYSCONFDIR) == -1) |
@@ -38,9 +97,11 @@ static inline char *get_fname(void) { | |||
38 | return fname; | 97 | return fname; |
39 | } | 98 | } |
40 | 99 | ||
100 | |||
41 | // returns 1 if the user is found in the database or if the database was not created | 101 | // returns 1 if the user is found in the database or if the database was not created |
42 | int firejail_user_check(const char *name) { | 102 | int firejail_user_check(const char *name) { |
43 | assert(name); | 103 | assert(name); |
104 | init_uid_gid_min(); | ||
44 | 105 | ||
45 | // root is allowed to run firejail by default | 106 | // root is allowed to run firejail by default |
46 | if (strcmp(name, "root") == 0) | 107 | if (strcmp(name, "root") == 0) |
@@ -48,7 +109,8 @@ int firejail_user_check(const char *name) { | |||
48 | 109 | ||
49 | // other system users will run the program as is | 110 | // other system users will run the program as is |
50 | uid_t uid = getuid(); | 111 | uid_t uid = getuid(); |
51 | if ((uid < UID_MIN && uid != 0) || strcmp(name, "nobody") == 0) | 112 | assert(uid_min > 0); |
113 | if (((int) uid < uid_min && uid != 0) || strcmp(name, "nobody") == 0) | ||
52 | return 0; | 114 | return 0; |
53 | 115 | ||
54 | // check file existence | 116 | // check file existence |