From nobody Wed Feb 14 06:05:44 2024 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 4TZSNn1qWtz5B4wm; Wed, 14 Feb 2024 06:05:45 +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 4TZSNn0kvjz4RX2; Wed, 14 Feb 2024 06:05:45 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1707890745; 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=UVdt4fil3sboSgYb7oOMGbDUCHfGNKIc/I0oNXqsIrc=; b=ba/MOFqv1HYtCO60DMSF8BMWVxYMopgqMAElWOigg4vzCvxJxvr8H9sU7obqq0R6pZPula JSd9nAHhGOPSdiatRCT9liG2m9T6TpgYp9VsvE505tomvvirBfK4r+I6UbHMnW8jPiGMI1 UJWPE99q3TUZbrxdS7eu9Y8Ee6KoHSgbMOkLEL2XuAet9+QHyeL3S76HPBnlSu3qr6T97X WWZBcdGjaS9QquVolcTUQnutUDIPhHGVXtcZDDE8mfpolJLbIatRfqqW7NEcSX6cplalUU V1liqwxy3kUb7/feiWnBTWjU24zYnt86kMoWQWnr92oh5xgRex4kAKr+zaEjEQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1707890745; a=rsa-sha256; cv=none; b=schPViaaVV8AyQ2j+GuNVvXVFXTgQ8gtZXWmCt3HwmNBKdrrxSj5osNtYRmEizdFUJdwsQ 2UDuHR6d8TCTtXRuDYhE2iS11cvkvi1rmSZEgCUBpLVLgtc3xnyRUbGcUm2Njf63qtxiRf UiiA0W3YmpFhCwhqD6fGxbUUm2hsvk8Lg6a2MJuboQCirxclAdG8KgFJkOxBfrK8a8GAAZ J6GvLEoNi2ovBJsr9I3ZbFe3zuI6r28q2GUlY36KpWi1VQ1ZIvkRarJzJ/BmprGm7yQE0e m0U1KQlAUu2Bj8s+nJJ8z3+Fu5DDxyjAjkL0JJPhm5tqvRy/96sLuDaobJGWvA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1707890745; 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=UVdt4fil3sboSgYb7oOMGbDUCHfGNKIc/I0oNXqsIrc=; b=O+9r4EN/DfBR74WwaCLbYGZA1xymRunpE/G5pjCnK+MsW6IpYP84oXePsbaB9GhYo8unoq Yi3+CJHgotnyGJ8BwjYujmMjzwm7o/oB4uS1WM8CiGwnQ0ugbMzfsQeeotmcNwgemPN8r+ bhByLxzK4ZAjw5X8y/maR8wkTHQkjWIhKL1zee1MFwklPFlyYgLTvFDhdD6exrKC0pon63 g5i2AXKELR05IdvzHMdcZzK9dBz/Z9Y2GrmMku5UO9IIN5YnthepP+VoCqAxdFEkwbXusK g1sXZizcFwJWBb6B+HiBIAcikmjn8iG5ahAH2xCEJ+sdJnjSrYxv7iiKDYs/Tg== 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 4TZSNm6yYNzmNW; Wed, 14 Feb 2024 06:05:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 41E65iEG084683; Wed, 14 Feb 2024 06:05:44 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 41E65ivI084681; Wed, 14 Feb 2024 06:05:44 GMT (envelope-from git) Date: Wed, 14 Feb 2024 06:05:44 GMT Message-Id: <202402140605.41E65ivI084681@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Gordon Tetlow Subject: git: f5bb597829e1 - releng/14.0 - bhyveload: use a dirfd to support -h 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: gordon X-Git-Repository: src X-Git-Refname: refs/heads/releng/14.0 X-Git-Reftype: branch X-Git-Commit: f5bb597829e13942648c4ab5726f1ff924e33e9f Auto-Submitted: auto-generated The branch releng/14.0 has been updated by gordon: URL: https://cgit.FreeBSD.org/src/commit/?id=f5bb597829e13942648c4ab5726f1ff924e33e9f commit f5bb597829e13942648c4ab5726f1ff924e33e9f Author: Kyle Evans AuthorDate: 2024-01-03 22:17:59 +0000 Commit: Gordon Tetlow CommitDate: 2024-02-14 05:41:59 +0000 bhyveload: use a dirfd to support -h Don't allow lookups from the loader scripts, which in rare cases may be in guest control depending on the setup, to leave the specified host root. Open the root dir and strictly do RESOLVE_BENEATH lookups from there. cb_open() has been restructured a bit to work nicely with this, using fdopendir() in the directory case and just using the fd we already opened in the regular file case. hostbase_open() was split out to provide an obvious place to apply rights(4) if that's something we care to do. Reviewed by: allanjude (earlier version), markj Approved by: so Security: FreeBSD-SA-24:01.bhyveload Security: CVE-2024-25940 (cherry picked from commit 6779d44bd878e3cf4723f7386b11da6508ab5431) (cherry picked from commit 426b28fdf700bcd8c05b25665da34f806b27b1bb) --- usr.sbin/bhyveload/bhyveload.c | 84 ++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c index 6b2633cac288..4c1dbd583e1f 100644 --- a/usr.sbin/bhyveload/bhyveload.c +++ b/usr.sbin/bhyveload/bhyveload.c @@ -88,11 +88,11 @@ #define NDISKS 32 -static char *host_base; static struct termios term, oldterm; static int disk_fd[NDISKS]; static int ndisks; static int consin_fd, consout_fd; +static int hostbase_fd = -1; static int need_reinit; @@ -159,42 +159,61 @@ static int cb_open(void *arg __unused, const char *filename, void **hp) { struct cb_file *cf; - char path[PATH_MAX]; + struct stat sb; + int fd, flags; - if (!host_base) + cf = NULL; + fd = -1; + flags = O_RDONLY | O_RESOLVE_BENEATH; + if (hostbase_fd == -1) return (ENOENT); - strlcpy(path, host_base, PATH_MAX); - if (path[strlen(path) - 1] == '/') - path[strlen(path) - 1] = 0; - strlcat(path, filename, PATH_MAX); - cf = malloc(sizeof(struct cb_file)); - if (stat(path, &cf->cf_stat) < 0) { - free(cf); + /* Absolute paths are relative to our hostbase, chop off leading /. */ + if (filename[0] == '/') + filename++; + + /* Lookup of /, use . instead. */ + if (filename[0] == '\0') + filename = "."; + + if (fstatat(hostbase_fd, filename, &sb, AT_RESOLVE_BENEATH) < 0) return (errno); + + if (!S_ISDIR(sb.st_mode) && !S_ISREG(sb.st_mode)) + return (EINVAL); + + if (S_ISDIR(sb.st_mode)) + flags |= O_DIRECTORY; + + /* May be opening the root dir */ + fd = openat(hostbase_fd, filename, flags); + if (fd < 0) + return (errno); + + cf = malloc(sizeof(struct cb_file)); + if (cf == NULL) { + close(fd); + return (ENOMEM); } + cf->cf_stat = sb; cf->cf_size = cf->cf_stat.st_size; + if (S_ISDIR(cf->cf_stat.st_mode)) { cf->cf_isdir = 1; - cf->cf_u.dir = opendir(path); - if (!cf->cf_u.dir) - goto out; - *hp = cf; - return (0); - } - if (S_ISREG(cf->cf_stat.st_mode)) { + cf->cf_u.dir = fdopendir(fd); + if (cf->cf_u.dir == NULL) { + close(fd); + free(cf); + return (ENOMEM); + } + } else { + assert(S_ISREG(cf->cf_stat.st_mode)); cf->cf_isdir = 0; - cf->cf_u.fd = open(path, O_RDONLY); - if (cf->cf_u.fd < 0) - goto out; - *hp = cf; - return (0); + cf->cf_u.fd = fd; } - -out: - free(cf); - return (EINVAL); + *hp = cf; + return (0); } static int @@ -714,6 +733,17 @@ usage(void) exit(1); } +static void +hostbase_open(const char *base) +{ + + if (hostbase_fd != -1) + close(hostbase_fd); + hostbase_fd = open(base, O_DIRECTORY | O_PATH); + if (hostbase_fd == -1) + err(EX_OSERR, "open"); +} + int main(int argc, char** argv) { @@ -748,7 +778,7 @@ main(int argc, char** argv) break; case 'h': - host_base = optarg; + hostbase_open(optarg); break; case 'l':