diff options
Diffstat (limited to 'libminijail.c')
-rw-r--r-- | libminijail.c | 85 |
1 files changed, 26 insertions, 59 deletions
diff --git a/libminijail.c b/libminijail.c index 0eca595..9915afe 100644 --- a/libminijail.c +++ b/libminijail.c @@ -13,7 +13,6 @@ #include <fcntl.h> #include <grp.h> #include <linux/capability.h> -#include <pwd.h> #include <sched.h> #include <signal.h> #include <stdbool.h> @@ -294,66 +293,26 @@ void API minijail_keep_supplementary_gids(struct minijail *j) { int API minijail_change_user(struct minijail *j, const char *user) { - char *buf = NULL; - struct passwd pw; - struct passwd *ppw = NULL; - ssize_t sz = sysconf(_SC_GETPW_R_SIZE_MAX); - if (sz == -1) - sz = 65536; /* your guess is as good as mine... */ - - /* - * sysconf(_SC_GETPW_R_SIZE_MAX), under glibc, is documented to return - * the maximum needed size of the buffer, so we don't have to search. - */ - buf = malloc(sz); - if (!buf) - return -ENOMEM; - getpwnam_r(user, &pw, buf, sz, &ppw); - /* - * We're safe to free the buffer here. The strings inside |pw| point - * inside |buf|, but we don't use any of them; this leaves the pointers - * dangling but it's safe. |ppw| points at |pw| if getpwnam_r(3) - * succeeded. - */ - free(buf); - /* getpwnam_r(3) does *not* set errno when |ppw| is NULL. */ - if (!ppw) - return -1; - minijail_change_uid(j, ppw->pw_uid); + uid_t uid; + gid_t gid; + int rc = lookup_user(user, &uid, &gid); + if (rc) + return rc; + minijail_change_uid(j, uid); j->user = strdup(user); if (!j->user) return -ENOMEM; - j->usergid = ppw->pw_gid; + j->usergid = gid; return 0; } int API minijail_change_group(struct minijail *j, const char *group) { - char *buf = NULL; - struct group gr; - struct group *pgr = NULL; - ssize_t sz = sysconf(_SC_GETGR_R_SIZE_MAX); - if (sz == -1) - sz = 65536; /* and mine is as good as yours, really */ - - /* - * sysconf(_SC_GETGR_R_SIZE_MAX), under glibc, is documented to return - * the maximum needed size of the buffer, so we don't have to search. - */ - buf = malloc(sz); - if (!buf) - return -ENOMEM; - getgrnam_r(group, &gr, buf, sz, &pgr); - /* - * We're safe to free the buffer here. The strings inside gr point - * inside buf, but we don't use any of them; this leaves the pointers - * dangling but it's safe. pgr points at gr if getgrnam_r succeeded. - */ - free(buf); - /* getgrnam_r(3) does *not* set errno when |pgr| is NULL. */ - if (!pgr) - return -1; - minijail_change_gid(j, pgr->gr_gid); + gid_t gid; + int rc = lookup_group(group, &gid); + if (rc) + return rc; + minijail_change_gid(j, gid); return 0; } @@ -1458,10 +1417,16 @@ static void write_ugid_maps_or_die(const struct minijail *j) static void enter_user_namespace(const struct minijail *j) { - if (j->uidmap && setresuid(0, 0, 0)) - pdie("user_namespaces: setresuid(0, 0, 0) failed"); - if (j->gidmap && setresgid(0, 0, 0)) - pdie("user_namespaces: setresgid(0, 0, 0) failed"); + int uid = j->flags.uid ? j->uid : 0; + int gid = j->flags.gid ? j->gid : 0; + if (j->gidmap && setresgid(gid, gid, gid)) { + pdie("user_namespaces: setresgid(%d, %d, %d) failed", gid, gid, + gid); + } + if (j->uidmap && setresuid(uid, uid, uid)) { + pdie("user_namespaces: setresuid(%d, %d, %d) failed", uid, uid, + uid); + } } static void parent_setup_complete(int *pipe_fds) @@ -1500,10 +1465,12 @@ static void drop_ugid(const struct minijail *j) } else if (j->flags.set_suppl_gids) { if (setgroups(j->suppl_gid_count, j->suppl_gid_list)) pdie("setgroups(suppl_gids) failed"); - } else if (!j->flags.keep_suppl_gids) { + } else if (!j->flags.keep_suppl_gids && !j->flags.disable_setgroups) { /* * Only attempt to clear supplementary groups if we are changing - * users or groups. + * users or groups, and if the caller did not request to disable + * setgroups (used when entering a user namespace as a + * non-privileged user). */ if ((j->flags.uid || j->flags.gid) && setgroups(0, NULL)) pdie("setgroups(0, NULL) failed"); |