]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
unshare: mount binfmt_misc
authorLaurent Vivier <laurent@vivier.eu>
Wed, 19 Jun 2024 08:19:50 +0000 (10:19 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 19 Jun 2024 10:39:56 +0000 (12:39 +0200)
add --mount-binfmt[=<dir>] to mount binfmt_misc filesystem,
this results in clearing inherited interpreters from the previous namespace

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
include/pathnames.h
sys-utils/unshare.1.adoc
sys-utils/unshare.c

index 81fa405f63c7fdd19dc25134bdef71dfaffb27cf..569bef17f982c6332bfaf5bf2c5c13da5e430392 100644 (file)
 /* sysctl fs paths */
 #define _PATH_PROC_SYS_FS      "/proc/sys/fs"
 #define _PATH_PROC_PIPE_MAX_SIZE       _PATH_PROC_SYS_FS "/pipe-max-size"
+#define _PATH_PROC_BINFMT_MISC _PATH_PROC_SYS_FS "/binfmt_misc"
 
 /* irqtop paths */
 #define _PATH_PROC_INTERRUPTS  "/proc/interrupts"
index e6201e28fffd46052648654f43ffac76a7dd7b06..48d1a55792827b48335358252d3ca22e10c7c8a3 100644 (file)
@@ -90,6 +90,9 @@ When *unshare* terminates, have _signame_ be sent to the forked child process. C
 *--mount-proc*[**=**__mountpoint__]::
 Just before running the program, mount the proc filesystem at _mountpoint_ (default is _/proc_). This is useful when creating a new PID namespace. It also implies creating a new mount namespace since the _/proc_ mount would otherwise mess up existing programs on the system. The new proc filesystem is explicitly mounted as private (with *MS_PRIVATE*|*MS_REC*).
 
+*--mount-binfmt*[**=**__mountpoint__]::
+Just before running the program, mount the binfmt_misc filesystem at _mountpoint_ (default is /proc/sys/fs/binfmt_misc).  It also implies creating a new mount namespace since the binfmt_misc mount would otherwise mess up existing programs on the system.  The new binfmt_misc filesystem is explicitly mounted as private (with *MS_PRIVATE*|*MS_REC*).
+
 **--map-user=**__uid|name__::
 Run the program only after the current effective user ID has been mapped to _uid_. If this option is specified multiple times, the last occurrence takes precedence. This option implies *--user*.
 
index 57f3b8744fb5701807bce0a7bbd1047438ae7321..d79aa112595510efad8bd9adc84b0dad2f2ced0a 100644 (file)
@@ -760,6 +760,7 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_(" --kill-child[=<signame>]  when dying, kill the forked child (implies --fork)\n"
                "                             defaults to SIGKILL\n"), out);
        fputs(_(" --mount-proc[=<dir>]      mount proc filesystem first (implies --mount)\n"), out);
+       fputs(_(" --mount-binfmt[=<dir>]    mount binfmt filesystem first (implies --user and --mount)\n"), out);
        fputs(_(" --propagation slave|shared|private|unchanged\n"
                "                           modify mount propagation in mount namespace\n"), out);
        fputs(_(" --setgroups allow|deny    control the setgroups syscall in user namespaces\n"), out);
@@ -783,6 +784,7 @@ int main(int argc, char *argv[])
 {
        enum {
                OPT_MOUNTPROC = CHAR_MAX + 1,
+               OPT_MOUNTBINFMT,
                OPT_PROPAGATION,
                OPT_SETGROUPS,
                OPT_KILLCHILD,
@@ -811,6 +813,7 @@ int main(int argc, char *argv[])
                { "fork",          no_argument,       NULL, 'f'             },
                { "kill-child",    optional_argument, NULL, OPT_KILLCHILD   },
                { "mount-proc",    optional_argument, NULL, OPT_MOUNTPROC   },
+               { "mount-binfmt",  optional_argument, NULL, OPT_MOUNTBINFMT },
                { "map-user",      required_argument, NULL, OPT_MAPUSER     },
                { "map-users",     required_argument, NULL, OPT_MAPUSERS    },
                { "map-group",     required_argument, NULL, OPT_MAPGROUP    },
@@ -839,6 +842,7 @@ int main(int argc, char *argv[])
        struct map_range *groupmap = NULL;
        int kill_child_signo = 0; /* 0 means --kill-child was not used */
        const char *procmnt = NULL;
+       const char *binfmt_mnt = NULL;
        const char *newroot = NULL;
        const char *newdir = NULL;
        pid_t pid_bind = 0, pid_idmap = 0;
@@ -913,6 +917,15 @@ int main(int argc, char *argv[])
                        unshare_flags |= CLONE_NEWNS;
                        procmnt = optarg ? optarg : "/proc";
                        break;
+               case OPT_MOUNTBINFMT:
+                       unshare_flags |= CLONE_NEWNS | CLONE_NEWUSER;
+                       binfmt_mnt = optarg;
+                       if (!binfmt_mnt) {
+                               if (!procmnt)
+                                       procmnt = "/proc";
+                               binfmt_mnt = _PATH_PROC_BINFMT_MISC;
+                       }
+                       break;
                case OPT_MAPUSER:
                        unshare_flags |= CLONE_NEWUSER;
                        mapuser = get_user(optarg, _("failed to parse uid"));
@@ -1178,6 +1191,12 @@ int main(int argc, char *argv[])
                        err(EXIT_FAILURE, _("mount %s failed"), procmnt);
        }
 
+       if (binfmt_mnt) {
+               if (mount("binfmt_misc", binfmt_mnt, "binfmt_misc",
+                         MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0)
+                       err(EXIT_FAILURE, _("mount %s failed"), binfmt_mnt);
+       }
+
        if (force_gid) {
                if (setgroups(0, NULL) != 0)    /* drop supplementary groups */
                        err(EXIT_FAILURE, _("setgroups failed"));