From: David Gibson Date: Wed, 29 Mar 2023 02:51:10 +0000 (+1100) Subject: Add --keep-caps option to nsenter, similar to the one in unshare X-Git-Tag: v2.40-rc1~464^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b175fa9f03062a11618983199f38578b6e11217;p=thirdparty%2Futil-linux.git Add --keep-caps option to nsenter, similar to the one in unshare When entering a user namespace at the kernel level, whether with clone(2), unshare(2) or setns(2), a process always gains full capabilities in the new userns. unshare(1) allows using that from the shell with the --keep-caps option, which transfers that full permitted capability set to the ambient set so it's available to the spawned shell or other process. nsenter(1) currently has no equivalent option, despite the fact that setns(2) grants capabilities in just the same way. This patch adds a --keep-caps to nsenter(1) that works just like the one in unshare(1). Signed-off-by: David Gibson --- diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am index a0bf6cb7b0..2584281fb7 100644 --- a/sys-utils/Makemodule.am +++ b/sys-utils/Makemodule.am @@ -524,7 +524,8 @@ if BUILD_NSENTER usrbin_exec_PROGRAMS += nsenter MANPAGES += sys-utils/nsenter.1 dist_noinst_DATA += sys-utils/nsenter.1.adoc -nsenter_SOURCES = sys-utils/nsenter.c lib/exec_shell.c +nsenter_SOURCES = sys-utils/nsenter.c lib/exec_shell.c \ + lib/caputils.c nsenter_LDADD = $(LDADD) libcommon.la $(SELINUX_LIBS) if HAVE_STATIC_NSENTER diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c index c2c20128f0..b0dab7df48 100644 --- a/sys-utils/nsenter.c +++ b/sys-utils/nsenter.c @@ -45,6 +45,7 @@ #include "xalloc.h" #include "all-io.h" #include "env.h" +#include "caputils.h" static struct namespace_file { int nstype; @@ -95,6 +96,7 @@ static void __attribute__((__noreturn__)) usage(void) 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(_(" --keep-caps retain capabilities granted in user namespaces\n"), out); fputs(_(" -r, --root[=] set the root directory\n"), out); fputs(_(" -w, --wd[=] set the working directory\n"), out); fputs(_(" -W, --wdns set the working directory in namespace\n"), out); @@ -232,7 +234,8 @@ static void continue_as_child(void) int main(int argc, char *argv[]) { enum { - OPT_PRESERVE_CRED = CHAR_MAX + 1 + OPT_PRESERVE_CRED = CHAR_MAX + 1, + OPT_KEEPCAPS, }; static const struct option longopts[] = { { "all", no_argument, NULL, 'a' }, @@ -255,6 +258,7 @@ int main(int argc, char *argv[]) { "env", no_argument, NULL, 'e' }, { "no-fork", no_argument, NULL, 'F' }, { "preserve-credentials", no_argument, NULL, OPT_PRESERVE_CRED }, + { "keep-caps", no_argument, NULL, OPT_KEEPCAPS }, #ifdef HAVE_LIBSELINUX { "follow-context", no_argument, NULL, 'Z' }, #endif @@ -274,6 +278,7 @@ int main(int argc, char *argv[]) char *wdns = NULL; uid_t uid = 0; gid_t gid = 0; + int keepcaps = 0; struct ul_env_list *envls; #ifdef HAVE_LIBSELINUX bool selinux = 0; @@ -384,6 +389,9 @@ int main(int argc, char *argv[]) case OPT_PRESERVE_CRED: preserve_cred = 1; break; + case OPT_KEEPCAPS: + keepcaps = 1; + break; #ifdef HAVE_LIBSELINUX case 'Z': selinux = 1; @@ -569,6 +577,9 @@ int main(int argc, char *argv[]) err(EXIT_FAILURE, _("setuid failed")); } + if (keepcaps && (namespaces & CLONE_NEWUSER)) + cap_permitted_to_ambient(); + if (optind < argc) { execvp(argv[optind], argv + optind); errexec(argv[optind]);