]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
Add --keep-caps option to nsenter, similar to the one in unshare
authorDavid Gibson <david@gibson.dropbear.id.au>
Wed, 29 Mar 2023 02:51:10 +0000 (13:51 +1100)
committerDavid Gibson <david@gibson.dropbear.id.au>
Wed, 29 Mar 2023 02:51:10 +0000 (13:51 +1100)
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 <david@gibson.dropbear.id.au>
sys-utils/Makemodule.am
sys-utils/nsenter.c

index a0bf6cb7b037d1224e239d52d325e5b08701c808..2584281fb7cd05a3b08fd83efd68650a73948161 100644 (file)
@@ -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
index c2c20128f0ac442ff20f8f40bf593032c2d61d37..b0dab7df48b4aaa91e26538dd938c55a6bcdce43 100644 (file)
@@ -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[=<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(_("     --keep-caps        retain capabilities granted in user namespaces\n"), out);
        fputs(_(" -r, --root[=<dir>]     set the root directory\n"), out);
        fputs(_(" -w, --wd[=<dir>]       set the working directory\n"), out);
        fputs(_(" -W, --wdns <dir>       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]);