From: Thomas Weißschuh Date: Fri, 3 Mar 2023 01:39:27 +0000 (+0000) Subject: nsenter: read default UID and GID from target process X-Git-Tag: v2.39-rc1~19^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=597ae346491f142ff3bf00f07110f8de22121fd7;p=thirdparty%2Futil-linux.git nsenter: read default UID and GID from target process Signed-off-by: Thomas Weißschuh --- diff --git a/Documentation/TODO b/Documentation/TODO index e1ee613621..52321d4319 100644 --- a/Documentation/TODO +++ b/Documentation/TODO @@ -66,11 +66,6 @@ lscpu - read cpuid and uname information from file if --sysroot is specified, then we can prepare regression tests completely independent on hw and architecture. -nsenter(1) ----------- - - read the default UID and GID from the target process. - http://thread.gmane.org/gmane.linux.utilities.util-linux-ng/9553/focus=9585 - hwclock ------ - use /var/lib/hwclock/drift to store hw-clock drift numbers. diff --git a/sys-utils/nsenter.1.adoc b/sys-utils/nsenter.1.adoc index 2500ff2071..513d2aa574 100644 --- a/sys-utils/nsenter.1.adoc +++ b/sys-utils/nsenter.1.adoc @@ -103,11 +103,15 @@ Enter the cgroup namespace. If no file is specified, enter the cgroup namespace *-T*, *--time*[=_file_]:: Enter the time namespace. If no file is specified, enter the time namespace of the target process. If _file_ is specified, enter the time namespace specified by _file_. -*-G*, *--setgid* _gid_:: -Set the group ID which will be used in the entered namespace and drop supplementary groups. *nsenter* always sets GID for user namespaces, the default is 0. - -*-S*, *--setuid* _uid_:: -Set the user ID which will be used in the entered namespace. *nsenter* always sets UID for user namespaces, the default is 0. +*-G*, *--setgid*[=_gid_]:: +Set the group ID which will be used in the entered namespace and drop supplementary groups. +*nsenter* always sets GID for user namespaces, the default is 0. +If no argument is specified the GID of the target process is used. + +*-S*, *--setuid*[=_uid_]:: +Set the user ID which will be used in the entered namespace. +*nsenter* always sets UID for user namespaces, the default is 0. +If no argument is specified the UID of the target process is used. *--preserve-credentials*:: Don't modify UID and GID when enter user namespace. The default is to drops supplementary groups and sets GID and UID to 0. diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c index 440bf3b9f8..c55cf173c3 100644 --- a/sys-utils/nsenter.c +++ b/sys-utils/nsenter.c @@ -89,8 +89,8 @@ static void __attribute__((__noreturn__)) usage(void) fputs(_(" -C, --cgroup[=] enter cgroup namespace\n"), out); fputs(_(" -U, --user[=] enter user namespace\n"), out); fputs(_(" -T, --time[=] enter time namespace\n"), out); - fputs(_(" -S, --setuid set uid in entered namespace\n"), out); - fputs(_(" -G, --setgid set gid in entered namespace\n"), out); + fputs(_(" -S, --setuid=[] set uid in entered namespace\n"), out); + fputs(_(" -G, --setgid=[] set gid in entered namespace\n"), out); fputs(_(" --preserve-credentials do not touch uids or gids\n"), out); fputs(_(" -r, --root[=] set the root directory\n"), out); fputs(_(" -w, --wd[=] set the working directory\n"), out); @@ -110,6 +110,7 @@ static void __attribute__((__noreturn__)) usage(void) static pid_t namespace_target_pid = 0; static int root_fd = -1; static int wd_fd = -1; +static int uid_gid_fd = -1; static void open_target_fd(int *fd, const char *type, const char *path) { @@ -241,8 +242,8 @@ int main(int argc, char *argv[]) { "user", optional_argument, NULL, 'U' }, { "cgroup", optional_argument, NULL, 'C' }, { "time", optional_argument, NULL, 'T' }, - { "setuid", required_argument, NULL, 'S' }, - { "setgid", required_argument, NULL, 'G' }, + { "setuid", optional_argument, NULL, 'S' }, + { "setgid", optional_argument, NULL, 'G' }, { "root", optional_argument, NULL, 'r' }, { "wd", optional_argument, NULL, 'w' }, { "wdns", optional_argument, NULL, 'W' }, @@ -261,7 +262,7 @@ int main(int argc, char *argv[]) struct namespace_file *nsfile; int c, pass, namespaces = 0, setgroups_nerrs = 0, preserve_cred = 0; - bool do_rd = false, do_wd = false, force_uid = false, force_gid = false; + bool do_rd = false, do_wd = false, do_uid = false, force_uid = false, do_gid = false, force_gid = false; bool do_all = false; int do_fork = -1; /* unknown yet */ char *wdns = NULL; @@ -277,7 +278,7 @@ int main(int argc, char *argv[]) close_stdout_atexit(); while ((c = - getopt_long(argc, argv, "+ahVt:m::u::i::n::p::C::U::T::S:G:r::w::W:FZ", + getopt_long(argc, argv, "+ahVt:m::u::i::n::p::C::U::T::S::G::r::w::W:FZ", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); @@ -339,11 +340,17 @@ int main(int argc, char *argv[]) namespaces |= CLONE_NEWTIME; break; case 'S': - uid = strtoul_or_err(optarg, _("failed to parse uid")); + if (optarg) + uid = strtoul_or_err(optarg, _("failed to parse uid")); + else + do_uid = true; force_uid = true; break; case 'G': - gid = strtoul_or_err(optarg, _("failed to parse gid")); + if (optarg) + gid = strtoul_or_err(optarg, _("failed to parse gid")); + else + do_gid = true; force_gid = true; break; case 'F': @@ -420,6 +427,8 @@ int main(int argc, char *argv[]) open_target_fd(&root_fd, "root", NULL); if (do_wd) open_target_fd(&wd_fd, "cwd", NULL); + if (do_uid || do_gid) + open_target_fd(&uid_gid_fd, "", NULL); /* * Update namespaces variable to contain all requested namespaces @@ -510,6 +519,21 @@ int main(int argc, char *argv[]) wd_fd = -1; } + if (uid_gid_fd >= 0) { + struct stat st; + + if (fstat(uid_gid_fd, &st) > 0) + err(EXIT_FAILURE, _("can not get process stat")); + + close(uid_gid_fd); + uid_gid_fd = -1; + + if (do_uid) + uid = st.st_uid; + if (do_gid) + gid = st.st_gid; + } + if (do_fork == 1) continue_as_child();