From nobody Thu Dec 8 14:32:35 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NSc7S0x5Mz4jcqf; Thu, 8 Dec 2022 14:32:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NSc7S0QXzz3hR8; Thu, 8 Dec 2022 14:32:36 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1670509956; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6frbmScHub4H20SQ70YONa/QpMTZlIgyUfc2dH6qy2E=; b=LVo8K3y9kdHb2/J2qZalV6ZEjO6sC6bwr23nZ02SSuInORDcqMF07PalbS++anUmU8yC0u qgtywEHztn17N4AdifHA1C9zGpb+KAxJmik83PtKyy46CvjTKfhj6rjPOzJAxYfB3DRwxV QTkzA08yDiy4t45J0piqiGvAFt27Vth/wXUBerMUfWmRavcCLzmUspYIjZXIAsdh4+bO6b LDYl/ZD/imNrjUi+Snv3UViiZY54kt/1jcnnilX8E6VBhjIPNS7ejdYpP7IbUT4pnP4dfZ M0QO1FUPpmE7yzVbDGrruJKpE59IatuBOSBp8yJ49mfooLZlrl70quZetrT7Zg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1670509956; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6frbmScHub4H20SQ70YONa/QpMTZlIgyUfc2dH6qy2E=; b=fAnxq63zz7ZyZEXfVrw9FdhYSNIyKDvt4MArgBRttdnJagqakl0afX9K5LKC+ZCME3FbgT PiCeuvAjPCkHGL33J9zOwAyZrE2Kxiw8xxx9UkNroQKXNg3wkwnQgp/rY9xkDpR1FV6Qpy UijoMwulTH19j3Nl1ETcF2HcPqZ2P5xJ70o8Aenj9FKKvH1LPbs6Es98V/zierMLUmKA84 eY9zxz7H1smx7hAqSaLs47O7eLSelvFk+uLbrZIqTO5LHOJ3lzQI46XhAvfqpyWRUBsUnf +vQGVr2+z9TLCLiFbGn6lxqjwh1CAdRxkwqfQRGDRSamgX7IEgmOxCvFGDmoig== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1670509956; a=rsa-sha256; cv=none; b=GTHchNlaLO2pgiLCVTLBTAgGsPjyKpBn7MtPZyTdlk5WrgVfnLuJlmaRC17obB6aL/BK5n fgYsFG1sAQfVpfAcI7xBRsNjeB2vAu/j4pu4Y4rgtkY0Y2FZVFbCFOZxKHQyxv7l7w8MgN TWC5jXot3X51FvkpHQJlxoIGNDOG5e4jXgTHr6c1QW47PVdI0VoTvK73THoncPicP1wQ0I GSpHM0nqy3UZfAZGYUH8Yg85oOKErkDYE0mrJi66XnLc13iFuVIuNTw8QNfPDCaB0nrIl4 U2eph257S0TlY7+452v/aEkVpx++u/cfRiiT5t74uicUw4qZiVCRbY4FtFtDsw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NSc7R6c4Sz105N; Thu, 8 Dec 2022 14:32:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2B8EWZ4V027691; Thu, 8 Dec 2022 14:32:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2B8EWZ9r027690; Thu, 8 Dec 2022 14:32:35 GMT (envelope-from git) Date: Thu, 8 Dec 2022 14:32:35 GMT Message-Id: <202212081432.2B8EWZ9r027690@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Doug Rabson Subject: git: 5eeb4f737f11 - main - imgact_binmisc: Optionally pre-open the interpreter vnode List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dfr X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 5eeb4f737f11b253ac330ae459b05e30fd16d0e8 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by dfr: URL: https://cgit.FreeBSD.org/src/commit/?id=5eeb4f737f11b253ac330ae459b05e30fd16d0e8 commit 5eeb4f737f11b253ac330ae459b05e30fd16d0e8 Author: Doug Rabson AuthorDate: 2022-11-17 10:48:20 +0000 Commit: Doug Rabson CommitDate: 2022-12-08 14:32:03 +0000 imgact_binmisc: Optionally pre-open the interpreter vnode This allows the use of chroot and/or jail environments which depend on interpreters registed with imgact_binmisc to use emulator binaries from the host to emulate programs inside the chroot. Reviewed by: imp MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D37432 --- sys/kern/imgact_binmisc.c | 49 ++++++++++++++++++++++++++++++++++++---- sys/kern/kern_exec.c | 18 ++++++++++++++- sys/sys/imgact.h | 1 + sys/sys/imgact_binmisc.h | 3 ++- usr.sbin/binmiscctl/binmiscctl.8 | 8 +++++++ usr.sbin/binmiscctl/binmiscctl.c | 15 ++++++++---- 6 files changed, 83 insertions(+), 11 deletions(-) diff --git a/sys/kern/imgact_binmisc.c b/sys/kern/imgact_binmisc.c index 951822df06b1..65b2e8e409a6 100644 --- a/sys/kern/imgact_binmisc.c +++ b/sys/kern/imgact_binmisc.c @@ -30,15 +30,18 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include +#include #include @@ -63,6 +66,7 @@ typedef struct imgact_binmisc_entry { uint8_t *ibe_magic; uint8_t *ibe_mask; uint8_t *ibe_interpreter; + struct vnode *ibe_interpreter_vnode; ssize_t ibe_interp_offset; uint32_t ibe_interp_argcnt; uint32_t ibe_interp_length; @@ -114,7 +118,7 @@ static struct sx interp_list_sx; * Populate the entry with the information about the interpreter. */ static void -imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe) +imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe, int flags) { uint32_t len = 0, argc = 1; char t[IBE_INTERP_LEN_MAX]; @@ -150,6 +154,30 @@ imgact_binmisc_populate_interp(char *str, imgact_binmisc_entry_t *ibe) memcpy(ibe->ibe_interpreter, t, len); ibe->ibe_interp_argcnt = argc; ibe->ibe_interp_length = len; + + ibe->ibe_interpreter_vnode = NULL; + if (flags & IBF_PRE_OPEN) { + struct nameidata nd; + int error; + + tp = t; + while (*tp != '\0' && *tp != ' ') { + tp++; + } + *tp = '\0'; + NDINIT(&nd, LOOKUP, FOLLOW | ISOPEN, UIO_SYSSPACE, t); + + /* + * If there is an error, just stop now and fall back + * to the non pre-open case where we lookup during + * exec. + */ + error = namei(&nd); + if (error) + return; + + ibe->ibe_interpreter_vnode = nd.ni_vp; + } } /* @@ -167,7 +195,7 @@ imgact_binmisc_new_entry(ximgact_binmisc_entry_t *xbe, ssize_t interp_offset, ibe->ibe_name = malloc(namesz, M_BINMISC, M_WAITOK|M_ZERO); strlcpy(ibe->ibe_name, xbe->xbe_name, namesz); - imgact_binmisc_populate_interp(xbe->xbe_interpreter, ibe); + imgact_binmisc_populate_interp(xbe->xbe_interpreter, ibe, xbe->xbe_flags); ibe->ibe_magic = malloc(xbe->xbe_msize, M_BINMISC, M_WAITOK|M_ZERO); memcpy(ibe->ibe_magic, xbe->xbe_magic, xbe->xbe_msize); @@ -199,6 +227,8 @@ imgact_binmisc_destroy_entry(imgact_binmisc_entry_t *ibe) free(ibe->ibe_interpreter, M_BINMISC); if (ibe->ibe_name) free(ibe->ibe_name, M_BINMISC); + if (ibe->ibe_interpreter_vnode) + vrele(ibe->ibe_interpreter_vnode); if (ibe) free(ibe, M_BINMISC); } @@ -271,15 +301,20 @@ imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe) } } + /* + * Preallocate a new entry. We do this without holding the + * lock to avoid lock-order problems if IBF_PRE_OPEN is + * set. + */ + ibe = imgact_binmisc_new_entry(xbe, interp_offset, argv0_cnt); + INTERP_LIST_WLOCK(); if (imgact_binmisc_find_entry(xbe->xbe_name) != NULL) { INTERP_LIST_WUNLOCK(); + imgact_binmisc_destroy_entry(ibe); return (EEXIST); } - /* Preallocate a new entry. */ - ibe = imgact_binmisc_new_entry(xbe, interp_offset, argv0_cnt); - SLIST_INSERT_HEAD(&interpreter_list, ibe, link); interp_list_entry_count++; INTERP_LIST_WUNLOCK(); @@ -698,6 +733,10 @@ imgact_binmisc_exec(struct image_params *imgp) /* Catch ibe->ibe_argv0_cnt counting more #a than we did. */ MPASS(ibe->ibe_argv0_cnt == argv0_cnt); imgp->interpreter_name = imgp->args->begin_argv; + if (ibe->ibe_interpreter_vnode) { + imgp->interpreter_vp = ibe->ibe_interpreter_vnode; + vref(imgp->interpreter_vp); + } done: INTERP_LIST_RUNLOCK(); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index cb45d18fbb85..68dab42c25cc 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -504,6 +504,18 @@ interpret: imgp->execpath = args->fname; vn_lock(imgp->vp, LK_SHARED | LK_RETRY); } + } else if (imgp->interpreter_vp) { + /* + * An image activator has already provided an open vnode + */ + newtextvp = imgp->interpreter_vp; + imgp->interpreter_vp = NULL; + if (vn_fullpath(newtextvp, &imgp->execpath, + &imgp->freepath) != 0) + imgp->execpath = args->fname; + vn_lock(newtextvp, LK_SHARED | LK_RETRY); + AUDIT_ARG_VNODE1(newtextvp); + imgp->vp = newtextvp; } else { AUDIT_ARG_FD(args->fd); @@ -702,7 +714,11 @@ interpret: free(imgp->freepath, M_TEMP); imgp->freepath = NULL; /* set new name to that of the interpreter */ - args->fname = imgp->interpreter_name; + if (imgp->interpreter_vp) { + args->fname = NULL; + } else { + args->fname = imgp->interpreter_name; + } goto interpret; } diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 0be3e71604bf..963f53aa387b 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -94,6 +94,7 @@ struct image_params { u_int map_flags; #define IMGP_ASLR_SHARED_PAGE 0x1 uint32_t imgp_flags; + struct vnode *interpreter_vp; /* vnode of the interpreter */ }; #ifdef _KERNEL diff --git a/sys/sys/imgact_binmisc.h b/sys/sys/imgact_binmisc.h index 74ff68622075..37ae9dcdd774 100644 --- a/sys/sys/imgact_binmisc.h +++ b/sys/sys/imgact_binmisc.h @@ -57,8 +57,9 @@ _Static_assert(IBE_MAGIC_MAX <= IBE_MATCH_MAX, */ #define IBF_ENABLED 0x0001 /* Entry is active. */ #define IBF_USE_MASK 0x0002 /* Use mask on header magic field. */ +#define IBF_PRE_OPEN 0x0004 /* Cache the vnode for interpreter */ -#define IBF_VALID_UFLAGS 0x0003 /* Bits allowed from userland. */ +#define IBF_VALID_UFLAGS 0x0007 /* Bits allowed from userland. */ /* * Used with sysctlbyname() to pass imgact bin misc entries in and out of the diff --git a/usr.sbin/binmiscctl/binmiscctl.8 b/usr.sbin/binmiscctl/binmiscctl.8 index 82624cccd9ed..198997d22058 100644 --- a/usr.sbin/binmiscctl/binmiscctl.8 +++ b/usr.sbin/binmiscctl/binmiscctl.8 @@ -46,6 +46,7 @@ .Op Fl -mask Ar mask .Op Fl -offset Ar offset .Op Fl -set-enabled +.Op Fl -pre-open .Nm .Cm disable .Ar name @@ -87,6 +88,7 @@ Operation must be one of the following: .Op Fl -mask Ar mask .Op Fl -offset Ar offset .Op Fl -set-enabled +.Op Fl -pre-open .Xc Add a new activator entry in the kernel. You must specify a @@ -124,6 +126,12 @@ To enable the activator entry the option is used. The activator default state is disabled. .Pp +To make the interpreter automatically available in jails and chroots, +use the +.Fl -pre-open +option to allow the kernel to open the binary at configuration time +rather then lazily when the the interpreted program is started. +.Pp The interpreter .Ar path may also contain arguments for the interpreter including diff --git a/usr.sbin/binmiscctl/binmiscctl.c b/usr.sbin/binmiscctl/binmiscctl.c index 3c5e19def67b..2ec2cc3f64d4 100644 --- a/usr.sbin/binmiscctl/binmiscctl.c +++ b/usr.sbin/binmiscctl/binmiscctl.c @@ -75,7 +75,8 @@ static const struct { " --interpreter \\\n" "\t\t--magic [--mask ] \\\n" "\t\t--size [--offset ] \\\n" - "\t\t[--set-enabled]" + "\t\t[--set-enabled] \\\n" + "\t\t[--pre-open]" }, { CMD_REMOVE, @@ -122,6 +123,7 @@ add_opts[] = { { "magic", required_argument, NULL, 'm' }, { "offset", required_argument, NULL, 'o' }, { "size", required_argument, NULL, 's' }, + { "pre-open", no_argument, NULL, 'p' }, { NULL, 0, NULL, 0 } }; @@ -192,8 +194,9 @@ printxbe(ximgact_binmisc_entry_t *xbe) printf("name: %s\n", xbe->xbe_name); printf("interpreter: %s\n", xbe->xbe_interpreter); - printf("flags: %s%s\n", (flags & IBF_ENABLED) ? "ENABLED " : "", - (flags & IBF_USE_MASK) ? "USE_MASK " : ""); + printf("flags: %s%s%s\n", (flags & IBF_ENABLED) ? "ENABLED " : "", + (flags & IBF_USE_MASK) ? "USE_MASK " : "", + (flags & IBF_PRE_OPEN) ? "PRE_OPEN " : ""); printf("magic size: %u\n", xbe->xbe_msize); printf("magic offset: %u\n", xbe->xbe_moffset); @@ -291,7 +294,7 @@ add_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe) IBE_NAME_MAX); strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX); - while ((ch = getopt_long(argc, argv, "ei:m:M:o:s:", add_opts, NULL)) + while ((ch = getopt_long(argc, argv, "epi:m:M:o:s:", add_opts, NULL)) != -1) { switch(ch) { @@ -328,6 +331,10 @@ add_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe) xbe->xbe_msize); break; + case 'p': + xbe->xbe_flags |= IBF_PRE_OPEN; + break; + default: usage("Unknown argument: '%c'", ch); }