From: Patrick Steinhardt Date: Thu, 20 Jun 2019 09:45:27 +0000 (+0200) Subject: user: allow setting multiple groups without user namespaces X-Git-Tag: 2.9~13^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=91848d22bfe534e3bd11360d3cef26a3103ff0f9;p=platform%2Fupstream%2Fnsjail.git user: allow setting multiple groups without user namespaces When not using a user namespace, then we'll completely ignore whether multiple groups have been specified by the user and only set up the process's GID. With user namespaces, we in fact cannot set up supplementary groups as we have set up "/proc/self/setgroups" to deny any call to setgroups(2). But we can do better than that when not using user namespaces, as we're free to use that syscall. As nsjail(1) documents that "--group" can be specified multiple times without mentioning that this won't work with "--disable_clone_newuser", change the code to make that constellation work. --- diff --git a/user.cc b/user.cc index 674bf4c..84ee54c 100644 --- a/user.cc +++ b/user.cc @@ -242,18 +242,32 @@ bool initNsFromChild(nsjconf_t* nsjconf) { } /* - * Best effort because of /proc/self/setgroups + * Best effort because of /proc/self/setgroups. We deny + * setgroups(2) calls only if user namespaces are in use. */ - LOG_D("setgroups(0, NULL)"); - const gid_t* group_list = NULL; - if (setgroups(0, group_list) == -1) { - PLOG_D("setgroups(NULL) failed"); + std::vector groups; + std::string groupsString = "["; + if (!nsjconf->clone_newuser && nsjconf->gids.size() > 1) { + for (auto it = nsjconf->gids.begin() + 1; it != nsjconf->gids.end(); it++) { + groups.push_back(it->inside_id); + groupsString += std::to_string(it->inside_id); + if (it < nsjconf->gids.end() - 1) + groupsString += ", "; + } } + groupsString += "]"; if (!setResGid(nsjconf->gids[0].inside_id)) { PLOG_E("setresgid(%u)", nsjconf->gids[0].inside_id); return false; } + + LOG_D("setgroups(%lu, %s)", groups.size(), groupsString.c_str()); + if (setgroups(groups.size(), groups.data()) == -1) { + PLOG_D("setgroups(%lu, %s) failed", groups.size(), groupsString.c_str()); + return false; + } + if (!setResUid(nsjconf->uids[0].inside_id)) { PLOG_E("setresuid(%u)", nsjconf->uids[0].inside_id); return false;