Skip to content

Commit

Permalink
evaluate UID_MIN/GID_MID at runtime, remove compile time evaluation - f…
Browse files Browse the repository at this point in the history
…ixes #1964
  • Loading branch information
netblue30 committed Jun 4, 2018
1 parent df5c9f0 commit ac92833
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
10 changes: 4 additions & 6 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,14 @@ HAVE_CONTRIB_INSTALL=@HAVE_CONTRIB_INSTALL@
BUSYBOX_WORKAROUND=@BUSYBOX_WORKAROUND@
HAVE_SUID=@HAVE_SUID@

uids.h:; ./mkuid.sh

.PHONY: mylibs $(MYLIBS)
mylibs: $(MYLIBS)
$(MYLIBS): uids.h
$(MYLIBS):
$(MAKE) -C $@

.PHONY: apps $(APPS)
apps: $(APPS)
$(APPS): $(MYLIBS) uids.h
$(APPS): $(MYLIBS)
$(MAKE) -C $@

$(MANPAGES): $(wildcard src/man/*.txt)
Expand Down Expand Up @@ -73,7 +71,7 @@ distclean: clean
for dir in $(APPS) $(MYLIBS); do \
$(MAKE) -C $$dir distclean; \
done
rm -fr Makefile autom4te.cache config.log config.status config.h uids.h dummy.o src/common.mk
rm -fr Makefile autom4te.cache config.log config.status config.h dummy.o src/common.mk

realinstall:
# firejail executable
Expand Down Expand Up @@ -192,7 +190,7 @@ uninstall:
rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firemon
rm -f $(DESTDIR)/$(datarootdir)/bash-completion/completions/firecfg

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"
DISTFILES = "src etc platform contrib configure configure.ac dummy.c Makefile.in install.sh mkman.sh mketc.sh mkdeb.sh COPYING README RELNOTES"
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"

dist:
Expand Down
14 changes: 9 additions & 5 deletions src/firejail/restrict_users.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "firejail.h"
#include "../include/firejail_user.h"
#include <sys/mount.h>
#include <sys/stat.h>
#include <linux/limits.h>
Expand All @@ -26,7 +27,6 @@
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include "../../uids.h"

#define MAXBUF 1024

Expand Down Expand Up @@ -115,8 +115,9 @@ static void sanitize_passwd(void) {
struct stat s;
if (stat("/etc/passwd", &s) == -1)
return;
assert(uid_min);
if (arg_debug)
printf("Sanitizing /etc/passwd, UID_MIN %d\n", UID_MIN);
printf("Sanitizing /etc/passwd, UID_MIN %d\n", uid_min);
if (is_link("/etc/passwd")) {
fprintf(stderr, "Error: invalid /etc/passwd\n");
exit(1);
Expand Down Expand Up @@ -167,7 +168,8 @@ static void sanitize_passwd(void) {
int rv = sscanf(ptr, "%d:", &uid);
if (rv == 0 || uid < 0)
goto errout;
if (uid < UID_MIN || uid == 65534) { // on Debian platforms user nobody is 65534
assert(uid_min);
if (uid < uid_min || uid == 65534) { // on Debian platforms user nobody is 65534
fprintf(fpout, "%s", buf);
continue;
}
Expand Down Expand Up @@ -248,8 +250,9 @@ static void sanitize_group(void) {
struct stat s;
if (stat("/etc/group", &s) == -1)
return;
assert(gid_min);
if (arg_debug)
printf("Sanitizing /etc/group, GID_MIN %d\n", GID_MIN);
printf("Sanitizing /etc/group, GID_MIN %d\n", gid_min);
if (is_link("/etc/group")) {
fprintf(stderr, "Error: invalid /etc/group\n");
exit(1);
Expand Down Expand Up @@ -299,7 +302,8 @@ static void sanitize_group(void) {
int rv = sscanf(ptr, "%d:", &gid);
if (rv == 0 || gid < 0)
goto errout;
if (gid < GID_MIN || gid == 65534) { // on Debian platforms 65534 is group nogroup
assert(gid_min);
if (gid < gid_min || gid == 65534) { // on Debian platforms 65534 is group nogroup
if (copy_line(fpout, buf, ptr))
goto errout;
continue;
Expand Down
2 changes: 2 additions & 0 deletions src/include/firejail_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#ifndef FIREJAIL_USER_H
#define FIREJAIL_USER_H

extern int uid_min;
extern int gid_min;

// returns 1 if the user is found in the database or if the database was not created
int firejail_user_check(const char *name);
Expand Down
66 changes: 64 additions & 2 deletions src/lib/firejail_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,91 @@
// One username per line in the file

#include "../include/common.h"
#include "../include/firejail_user.h"
#include <sys/types.h>
#include <pwd.h>
#include "../../uids.h"

#define MAXBUF 4098

// minimum values for uid and gid extracted from /etc/login.defs
int uid_min = 0;
int gid_min = 0;

static void init_uid_gid_min(void) {
if (uid_min != 0 && gid_min != 0)
return;

// read the real values from login.def
FILE *fp = fopen("/etc/login.defs", "r");
if (!fp)
goto errexit;

char buf[MAXBUF];
while (fgets(buf, MAXBUF, fp)) {
// comments
if (*buf == '#')
continue;
// skip empty space
char *ptr = buf;
while (*ptr == ' ' || *ptr == '\t')
ptr++;

if (strncmp(ptr, "UID_MIN", 7) == 0) {
int rv = sscanf(ptr + 7, "%d", &uid_min);
if (rv != 1 || uid_min < 0) {
fclose(fp);
goto errexit;
}
}
else if (strncmp(ptr, "GID_MIN", 7) == 0) {
int rv = sscanf(ptr + 7, "%d", &gid_min);
if (rv != 1 || gid_min < 0) {
fclose(fp);
goto errexit;
}
}

if (uid_min != 0 && gid_min != 0)
break;

}
fclose(fp);

if (uid_min == 0 || gid_min == 0)
goto errexit;
//printf("uid_min %d, gid_min %d\n", uid_min, gid_min);

return;

errexit:
fprintf(stderr, "Error: cannot read UID_MIN and/or GID_MIN from /etc/login.defs, using 1000 by default\n");
uid_min = 1000;
gid_min = 1000;
}



static inline char *get_fname(void) {
char *fname;
if (asprintf(&fname, "%s/firejail.users", SYSCONFDIR) == -1)
errExit("asprintf");
return fname;
}


// returns 1 if the user is found in the database or if the database was not created
int firejail_user_check(const char *name) {
assert(name);
init_uid_gid_min();

// root is allowed to run firejail by default
if (strcmp(name, "root") == 0)
return 1;

// other system users will run the program as is
uid_t uid = getuid();
if ((uid < UID_MIN && uid != 0) || strcmp(name, "nobody") == 0)
assert(uid_min > 0);
if (((int) uid < uid_min && uid != 0) || strcmp(name, "nobody") == 0)
return 0;

// check file existence
Expand Down

0 comments on commit ac92833

Please sign in to comment.