summaryrefslogtreecommitdiffstats
path: root/sys-utils/nsenter.c
diff options
context:
space:
mode:
authorKarel Zak2015-01-08 12:52:43 +0100
committerKarel Zak2015-01-09 10:36:21 +0100
commite99a6626d6262266f012a20ae69c8e4573ee22fd (patch)
tree4b29fc9f9443bcfd55988198438f804a51cdc3b2 /sys-utils/nsenter.c
parentnsenter: keep semantic consistent (diff)
downloadkernel-qcow2-util-linux-e99a6626d6262266f012a20ae69c8e4573ee22fd.tar.gz
kernel-qcow2-util-linux-e99a6626d6262266f012a20ae69c8e4573ee22fd.tar.xz
kernel-qcow2-util-linux-e99a6626d6262266f012a20ae69c8e4573ee22fd.zip
nsenter: add --preserve-credentials and cleanup setgroups() usage
The new option --preserve-credentials completely disables all operations related to UIGs and GIDs. The patch also calls setgroups() before we enter user namespace (so root can always clear their groups) and after we enter user namespace (to detect /proc/self/setgroups "deny"). If both fail then nsenter complains. Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/nsenter.c')
-rw-r--r--sys-utils/nsenter.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c
index 50f77f381..b029f8087 100644
--- a/sys-utils/nsenter.c
+++ b/sys-utils/nsenter.c
@@ -78,6 +78,7 @@ static void usage(int status)
fputs(_(" -U, --user[=<file>] enter user namespace\n"), out);
fputs(_(" -S, --setuid <uid> set uid in entered namespace\n"), out);
fputs(_(" -G, --setgid <gid> set gid in entered namespace\n"), out);
+ fputs(_(" --preserve-credentials do not touch uids or gids\n"), out);
fputs(_(" -r, --root[=<dir>] set the root directory\n"), out);
fputs(_(" -w, --wd[=<dir>] set the working directory\n"), out);
fputs(_(" -F, --no-fork do not fork before exec'ing <program>\n"), out);
@@ -165,6 +166,9 @@ static void continue_as_child(void)
int main(int argc, char *argv[])
{
+ enum {
+ OPT_PRESERVE_CRED = CHAR_MAX + 1
+ };
static const struct option longopts[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V'},
@@ -180,11 +184,12 @@ int main(int argc, char *argv[])
{ "root", optional_argument, NULL, 'r' },
{ "wd", optional_argument, NULL, 'w' },
{ "no-fork", no_argument, NULL, 'F' },
+ { "preserve-credentials", no_argument, NULL, OPT_PRESERVE_CRED },
{ NULL, 0, NULL, 0 }
};
struct namespace_file *nsfile;
- int c, namespaces = 0;
+ int c, namespaces = 0, setgroups_nerrs = 0, preserve_cred = 0;
bool do_rd = false, do_wd = false, force_uid = false, force_gid = false;
int do_fork = -1; /* unknown yet */
uid_t uid = 0;
@@ -267,6 +272,9 @@ int main(int argc, char *argv[])
else
do_wd = true;
break;
+ case OPT_PRESERVE_CRED:
+ preserve_cred = 1;
+ break;
default:
usage(EXIT_FAILURE);
}
@@ -292,6 +300,17 @@ int main(int argc, char *argv[])
namespaces |= nsfile->nstype;
}
+ /* for user namespaces we always set UID and GID (default is 0)
+ * and clear root's groups if --preserve-credentials is no specified */
+ if ((namespaces & CLONE_NEWUSER) && !preserve_cred) {
+ force_uid = true, force_gid = true;
+
+ /* We call setgroups() before and after we enter user namespace,
+ * let's complain only if both fail */
+ if (setgroups(0, NULL) != 0)
+ setgroups_nerrs++;
+ }
+
/*
* Now that we know which namespaces we want to enter, enter them.
*/
@@ -342,12 +361,8 @@ int main(int argc, char *argv[])
if (do_fork == 1)
continue_as_child();
- /* for user namespaces we always set UID and GID (default is 0) */
- if (namespaces & CLONE_NEWUSER)
- force_uid = true, force_gid = true;
-
if (force_uid || force_gid) {
- if (force_gid && setgroups(0, NULL)) /* drop supplementary groups */
+ if (force_gid && setgroups(0, NULL) != 0 && setgroups_nerrs) /* drop supplementary groups */
err(EXIT_FAILURE, _("setgroups failed"));
if (force_gid && setgid(gid) < 0) /* change GID */
err(EXIT_FAILURE, _("setgid failed"));