From: Laurent Vivier <laurent@vivier.eu>
To: util-linux@vger.kernel.org
Cc: Laurent Vivier <laurent@vivier.eu>
Subject: [PATCH v2 2/2] unshare: load binfmt_misc interpreter
Date: Tue, 11 Jun 2024 10:43:14 +0200 [thread overview]
Message-ID: <20240611084314.183913-3-laurent@vivier.eu> (raw)
In-Reply-To: <20240611084314.183913-1-laurent@vivier.eu>
add -l, --load-interp <file> to load a binfmt_misc interpreter at startup.
The interpreter is loaded from the initial fileystem if the 'F' flags is
provided, otherwise from inside the new namespace
This makes possible to start a chroot of another architecture without
being root.
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
Notes:
v2:
- use <binfmt_mnt>/register rather than _PATH_PROC_BINFMT_MISC_REGISTER
to load the interpreter
sys-utils/unshare.1.adoc | 10 ++++++++
sys-utils/unshare.c | 52 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/sys-utils/unshare.1.adoc b/sys-utils/unshare.1.adoc
index 48d1a5579282..24ac6fb01867 100644
--- a/sys-utils/unshare.1.adoc
+++ b/sys-utils/unshare.1.adoc
@@ -138,6 +138,9 @@ Set the user ID which will be used in the entered namespace.
*-G*, *--setgid* _gid_::
Set the group ID which will be used in the entered namespace and drop supplementary groups.
+*-l*, **--load-interp=**__file__::
+Load binfmt_misc definition in the namespace (implies *--mount-binfmt*).
+
*--monotonic* _offset_::
Set the offset of *CLOCK_MONOTONIC* which will be used in the entered time namespace. This option requires unsharing a time namespace with *--time*.
@@ -256,6 +259,13 @@ up 21 hours, 30 minutes
up 9 years, 28 weeks, 1 day, 2 hours, 50 minutes
....
+The following example execute a chroot into the directory /chroot/powerpc/jessie and install the interpreter /bin/qemu-ppc-static to execute the powerpc binaries.
+If the interpreter is defined with the flag F, the interpreter is loaded before the chroot otherwise the interpreter is loaded from inside the chroot.
+
+....
+$ unshare --map-root-user --fork --pid --load-interp=":qemu-ppc:M::\\x7fELF\x01\\x02\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x14:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff:/bin/qemu-ppc-static:OCF" --root=/chroot/powerpc/jessie /bin/bash -l
+....
+
== AUTHORS
mailto:dottedmag@dottedmag.net[Mikhail Gusarov],
diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
index d79aa1125955..f8e1141840ca 100644
--- a/sys-utils/unshare.c
+++ b/sys-utils/unshare.c
@@ -725,6 +725,35 @@ static pid_t map_ids_from_child(int *fd, uid_t mapuser,
exit(EXIT_SUCCESS);
}
+static int is_fixed(const char *interp)
+{
+ const char *flags;
+
+ flags = strrchr(interp, ':');
+
+ return strchr(flags, 'F') != NULL;
+}
+
+static void load_interp(const char *binfmt_mnt, const char *interp)
+{
+ int dirfd, fd;
+
+ dirfd = open(binfmt_mnt, O_PATH | O_DIRECTORY);
+ if (dirfd < 0)
+ err(EXIT_FAILURE, _("cannot open %s"), binfmt_mnt);
+
+ fd = openat(dirfd, "register", O_WRONLY);
+ if (fd < 0)
+ err(EXIT_FAILURE, _("cannot open %s/register"), binfmt_mnt);
+
+ if (write_all(fd, interp, strlen(interp)))
+ err(EXIT_FAILURE, _("write failed %s/register"), binfmt_mnt);
+
+ close(fd);
+
+ close(dirfd);
+}
+
static void __attribute__((__noreturn__)) usage(void)
{
FILE *out = stdout;
@@ -772,6 +801,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" -G, --setgid <gid> set gid in entered namespace\n"), out);
fputs(_(" --monotonic <offset> set clock monotonic offset (seconds) in time namespaces\n"), out);
fputs(_(" --boottime <offset> set clock boottime offset (seconds) in time namespaces\n"), out);
+ fputs(_(" -l, --load-interp <file> load binfmt definition in the namespace (implies --mount-binfmt)\n"), out);
fputs(USAGE_SEPARATOR, out);
fprintf(out, USAGE_HELP_OPTIONS(27));
@@ -830,6 +860,7 @@ int main(int argc, char *argv[])
{ "wd", required_argument, NULL, 'w' },
{ "monotonic", required_argument, NULL, OPT_MONOTONIC },
{ "boottime", required_argument, NULL, OPT_BOOTTIME },
+ { "load-interp", required_argument, NULL, 'l' },
{ NULL, 0, NULL, 0 }
};
@@ -846,6 +877,7 @@ int main(int argc, char *argv[])
const char *newroot = NULL;
const char *newdir = NULL;
pid_t pid_bind = 0, pid_idmap = 0;
+ const char *newinterp = NULL;
pid_t pid = 0;
#ifdef UL_HAVE_PIDFD
int fd_parent_pid = -1;
@@ -868,7 +900,7 @@ int main(int argc, char *argv[])
textdomain(PACKAGE);
close_stdout_atexit();
- while ((c = getopt_long(argc, argv, "+fhVmuinpCTUrR:w:S:G:c", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "+fhVmuinpCTUrR:w:S:G:cl:", longopts, NULL)) != -1) {
switch (c) {
case 'f':
forkit = 1;
@@ -1011,6 +1043,15 @@ int main(int argc, char *argv[])
boottime = strtos64_or_err(optarg, _("failed to parse boottime offset"));
force_boottime = 1;
break;
+ case 'l':
+ unshare_flags |= CLONE_NEWNS | CLONE_NEWUSER;
+ if (!binfmt_mnt) {
+ if (!procmnt)
+ procmnt = "/proc";
+ binfmt_mnt = _PATH_PROC_BINFMT_MISC;
+ }
+ newinterp = optarg;
+ break;
case 'h':
usage();
@@ -1165,6 +1206,13 @@ int main(int argc, char *argv[])
if ((unshare_flags & CLONE_NEWNS) && propagation)
set_propagation(propagation);
+ if (newinterp && is_fixed(newinterp)) {
+ if (mount("binfmt_misc", _PATH_PROC_BINFMT_MISC, "binfmt_misc",
+ MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0)
+ err(EXIT_FAILURE, _("mount %s failed"), _PATH_PROC_BINFMT_MISC);
+ load_interp(_PATH_PROC_BINFMT_MISC, newinterp);
+ }
+
if (newroot) {
if (chroot(newroot) != 0)
err(EXIT_FAILURE,
@@ -1196,6 +1244,8 @@ int main(int argc, char *argv[])
MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0)
err(EXIT_FAILURE, _("mount %s failed"), binfmt_mnt);
}
+ if (newinterp && !is_fixed(newinterp))
+ load_interp(binfmt_mnt, newinterp);
if (force_gid) {
if (setgroups(0, NULL) != 0) /* drop supplementary groups */
--
2.45.2
next prev parent reply other threads:[~2024-06-11 8:48 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-11 8:43 [PATCH v2 0/2] unshare: manage binfmt_misc mounts Laurent Vivier
2024-06-11 8:43 ` [PATCH v2 1/2] unshare: mount binfmt_misc Laurent Vivier
2024-06-11 8:43 ` Laurent Vivier [this message]
2024-06-18 9:51 ` [PATCH v2 2/2] unshare: load binfmt_misc interpreter Karel Zak
2024-06-18 10:13 ` Laurent Vivier
2024-06-18 11:58 ` Karel Zak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240611084314.183913-3-laurent@vivier.eu \
--to=laurent@vivier.eu \
--cc=util-linux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).