From nobody Fri Feb 18 14:52:23 2022 X-Original-To: dev-commits-src-branches@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 6244F19D70E1; Fri, 18 Feb 2022 14:52:23 +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 4K0ZRW2Lq1z3FRL; Fri, 18 Feb 2022 14:52:23 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1645195943; 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=X0e5sk22iDhX6+bBEK5iXm0JocFzuSziQskHrCRcDBk=; b=m0lFQouN0su9qAgQHOFQ9vFTAOcGZ4O9U2iLJEenunge4CCasJ9YS52Foq4RnwV39EvRKn C1ZgkMIb9HaAo1R1FHcVHR6O5kUVXCsnwXni8poByurc+1OsgM2P1/kgAHlKFYNnbxaynp tbG+/GXFu+CIcgDiv2PJ+8PXkMTfPJ7SF1Sw75/WXsZWVlE/BwLpmTYlCdrR+IiH8nLe0v Xp4kSKoICOMU4bs7l/yZXrKbO937iiPH/k5G8ABW+Vz5yIwQiZnjkF4IX3namQEVukOLZV Zbc6/jCwz54ndNoYUdtqYFmAj3G7qYtxXOxPX4dieF6gsYLF0loFf4UU74bnbA== 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 307331F812; Fri, 18 Feb 2022 14:52:23 +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 21IEqNFu077435; Fri, 18 Feb 2022 14:52:23 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 21IEqNrL077434; Fri, 18 Feb 2022 14:52:23 GMT (envelope-from git) Date: Fri, 18 Feb 2022 14:52:23 GMT Message-Id: <202202181452.21IEqNrL077434@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Edward Tomasz Napierala Subject: git: 460b4b550dc9 - stable/13 - Implement unprivileged chroot List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: trasz X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: 460b4b550dc9619f33a0d1af3870eaef60b04797 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1645195943; 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=X0e5sk22iDhX6+bBEK5iXm0JocFzuSziQskHrCRcDBk=; b=fTVnwGh3vBOxAMPUd/fQQZI1HhAxq12TJaq3xreE72qn9A0U+UwKV4q7m9aJzWoVQcFUSU Z0PU0YEcUJOQZRFGqLMOwux5JMIDION9+GI3pTQOz1mVH34WP1HgM1KePsA53/VcvUUcI3 V3PsXdg5wUtAVBbgofFf7gGqx2mcXn2mop9NK9IkZ6Pgr59lcZP7FmRkzI1re8Q47UEFRL lxWu146Qo4AYd6/dvgMt+h7zAXLxDT5gwZn+JecqdgZLLZledHFkm4Yi1j8lAXD0dgENm3 9zaplGoPek0MUrnNHQ4BuTU3bWej4X6aHXM7IJA4GrGOtxZTFUwRJB4N+MJx+w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1645195943; a=rsa-sha256; cv=none; b=QZDeV4MXBJf3/ObPf6D1btXxTChUU3fivleZCF9cGAN8Or16XsulXzrn/T0LENed4wME5B MxxjOeww74QHAwNM5IvOCIcbqTxENRKehwC2MdMMmOyo5aswyNUL5k9NpYYV6Gmo8rCsKX 9X0VcXIZbn3YFTalWeHD08yqLKRUM/LEloLZBxqclxOdqCCIPkj0EaCsG2/wJyB+4/ytTH +NOwKFUrYvRzueB3YfQOVo84D3hmf4/fSvabwAJ823eRIMfzpNxc1nS1tZZDJO7rf+5g7M Vpg6zxHubLn2GBeM3BhOOb1jBdB4lEmFJEciIjoihQcuFBcK55mBqCY9fi2leA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by trasz: URL: https://cgit.FreeBSD.org/src/commit/?id=460b4b550dc9619f33a0d1af3870eaef60b04797 commit 460b4b550dc9619f33a0d1af3870eaef60b04797 Author: Edward Tomasz Napierala AuthorDate: 2021-07-20 08:56:04 +0000 Commit: Edward Tomasz Napierala CommitDate: 2022-02-14 18:42:21 +0000 Implement unprivileged chroot This builds on recently introduced NO_NEW_PRIVS flag to implement unprivileged chroot, enabled by `security.bsd.unprivileged_chroot`. It allows non-root processes to chroot(2), provided they have the NO_NEW_PRIVS flag set. The chroot(8) utility gets a new flag, -n, which sets NO_NEW_PRIVS before chrooting. Reviewed By: kib Sponsored By: EPSRC Relnotes: yes Differential Revision: https://reviews.freebsd.org/D30130 (cherry picked from commit a40cf4175c90142442d0c6515f6c83956336699b) --- sys/kern/vfs_syscalls.c | 17 +++++++++++++++-- usr.sbin/chroot/chroot.8 | 13 ++++++++++++- usr.sbin/chroot/chroot.c | 20 +++++++++++++++++--- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 3d1e7d9c73fa..19a32a175895 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -956,6 +956,10 @@ kern_chdir(struct thread *td, const char *path, enum uio_seg pathseg) return (0); } +static int unprivileged_chroot = 0; +SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_chroot, CTLFLAG_RW, + &unprivileged_chroot, 0, + "Unprivileged processes can use chroot(2)"); /* * Change notion of root (``/'') directory. */ @@ -968,11 +972,20 @@ int sys_chroot(struct thread *td, struct chroot_args *uap) { struct nameidata nd; + struct proc *p; int error; error = priv_check(td, PRIV_VFS_CHROOT); - if (error != 0) - return (error); + if (error != 0) { + p = td->td_proc; + PROC_LOCK(p); + if (unprivileged_chroot == 0 || + (p->p_flag2 & P2_NO_NEW_PRIVS) == 0) { + PROC_UNLOCK(p); + return (error); + } + PROC_UNLOCK(p); + } NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE, uap->path, td); error = namei(&nd); diff --git a/usr.sbin/chroot/chroot.8 b/usr.sbin/chroot/chroot.8 index 977961abb6ec..9f5b2f380376 100644 --- a/usr.sbin/chroot/chroot.8 +++ b/usr.sbin/chroot/chroot.8 @@ -28,7 +28,7 @@ .\" @(#)chroot.8 8.1 (Berkeley) 6/9/93 .\" $FreeBSD$ .\" -.Dd June 27, 2020 +.Dd July 20, 2021 .Dt CHROOT 8 .Os .Sh NAME @@ -39,6 +39,7 @@ .Op Fl G Ar group Ns Op Cm \&, Ns Ar group ... .Op Fl g Ar group .Op Fl u Ar user +.Op Fl n .Ar newroot .Op Ar command Op Ar arg ... .Sh DESCRIPTION @@ -61,6 +62,16 @@ Run the command with the permissions of the specified .It Fl u Ar user Run the command as the .Ar user . +.It Fl n +Use the +.Dv PROC_NO_NEW_PRIVS_CTL +.Xr procctl 2 +command before chrooting, effectively disabling SUID/SGID bits +for the calling process and its descendants. +If +.Dv security.bsd.unprivileged_chroot +sysctl is set to 1, it will make it possible to chroot without +superuser privileges. .El .Sh ENVIRONMENT The following environment variable is referenced by diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c index 60ef631ca875..bb87ae6f0503 100644 --- a/usr.sbin/chroot/chroot.c +++ b/usr.sbin/chroot/chroot.c @@ -44,6 +44,7 @@ static char sccsid[] = "@(#)chroot.c 8.1 (Berkeley) 6/9/93"; __FBSDID("$FreeBSD$"); #include +#include #include #include @@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -67,13 +69,15 @@ main(int argc, char *argv[]) const char *shell; gid_t gid, *gidlist; uid_t uid; - int ch, gids; + int arg, ch, error, gids; long ngroups_max; + bool nonpriviledged; gid = 0; uid = 0; user = group = grouplist = NULL; - while ((ch = getopt(argc, argv, "G:g:u:")) != -1) { + nonpriviledged = false; + while ((ch = getopt(argc, argv, "G:g:u:n")) != -1) { switch(ch) { case 'u': user = optarg; @@ -90,6 +94,9 @@ main(int argc, char *argv[]) if (*grouplist == '\0') usage(); break; + case 'n': + nonpriviledged = true; + break; case '?': default: usage(); @@ -153,6 +160,13 @@ main(int argc, char *argv[]) } } + if (nonpriviledged) { + arg = PROC_NO_NEW_PRIVS_ENABLE; + error = procctl(P_PID, getpid(), PROC_NO_NEW_PRIVS_CTL, &arg); + if (error != 0) + err(1, "procctl"); + } + if (chdir(argv[0]) == -1 || chroot(".") == -1) err(1, "%s", argv[0]); @@ -179,6 +193,6 @@ static void usage(void) { (void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] " - "[-u user] newroot [command]\n"); + "[-u user] [-n ] newroot [command]\n"); exit(1); }