From owner-freebsd-bugs@FreeBSD.ORG Mon Feb 25 09:50:03 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B484216A40A for ; Mon, 25 Feb 2008 09:50:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 9229F13C500 for ; Mon, 25 Feb 2008 09:50:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m1P9o3bZ026349 for ; Mon, 25 Feb 2008 09:50:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m1P9o3w4026348; Mon, 25 Feb 2008 09:50:03 GMT (envelope-from gnats) Resent-Date: Mon, 25 Feb 2008 09:50:03 GMT Resent-Message-Id: <200802250950.m1P9o3w4026348@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Jille Timmermans Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1277716A405 for ; Mon, 25 Feb 2008 09:48:05 +0000 (UTC) (envelope-from quis@quis.cx) Received: from smtp4.versatel.nl (smtp4.versatel.nl [62.58.50.91]) by mx1.freebsd.org (Postfix) with ESMTP id 7362013C4F0 for ; Mon, 25 Feb 2008 09:48:04 +0000 (UTC) (envelope-from quis@quis.cx) Received: (qmail 3252 invoked by uid 0); 25 Feb 2008 09:21:17 -0000 Received: from ip83-113-174-82.adsl2.versatel.nl (HELO istud.quis.cx) ([82.174.113.83]) (envelope-sender ) by smtp4.versatel.nl (qmail-ldap-1.03) with SMTP for < >; 25 Feb 2008 09:21:17 -0000 Received: by istud.quis.cx (Postfix, from userid 1001) id 4DF633981F; Mon, 25 Feb 2008 10:21:17 +0100 (CET) Message-Id: <20080225092117.4DF633981F@istud.quis.cx> Date: Mon, 25 Feb 2008 10:21:17 +0100 (CET) From: Jille Timmermans To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: Ed Schouten Subject: kern/121073: Patch to run chroot as an unprivileged user X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Jille Timmermans List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Feb 2008 09:50:03 -0000 >Number: 121073 >Category: kern >Synopsis: Patch to run chroot as an unprivileged user >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Feb 25 09:50:03 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Jille Timmermans >Release: FreeBSD 8.0-CURRENT i386 >Organization: >Environment: System: FreeBSD stagemachine 8.0-CURRENT FreeBSD 8.0-CURRENT #0: Mon Feb 25 09:24:13 CET 2008 ed@stagemachine:/usr/obj/store/home/ed/p4/mpsafetty/sys/STAGEMACHINE i386 >Description: We (Ed and I) thought it should be possible to chroot as non-root, This should (hopefully) increase the security, because no setuid-root and privilege dropping after the chroot(2) call is longer needed. This is tested on 8.0-CURRENT, should work on 7.0-RC2 and I will backport it later to 6.3-RELEASE. >How-To-Repeat: sysctl kern.chroot_allow_unprivileged=1 su nobody chroot / sh ping 127.0.0.1 # Should fail >Fix: --- lib/libc/sys/chroot.2 +++ lib/libc/sys/chroot.2 @@ -61,7 +61,13 @@ .Fn chroot has no effect on the process's current directory. .Pp -This call is restricted to the super-user. +By default, this call is restricted to the super-user. If +.Ql kern.chroot_allow_unprivileged +is set to a non-zero value, all users are capable of performing the +.Fn chroot +call. When called by an unprivileged user, the process and its children +won't honor the setuid and setgid bits when performing an +.Xr execve 2 . .Pp Depending on the setting of the .Ql kern.chroot_allow_open_directories @@ -140,3 +146,8 @@ open directories, or a MAC check), it is possible that this system call may return an error, with the working directory of the process left changed. +.Pp +When a call to +.Fn chroot +fails when invoked by an unprivileged user, the process is not properly +capable of executing setuid or setgid applications anymore. --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -560,7 +560,7 @@ if (credential_changing && (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 && - (p->p_flag & P_TRACED) == 0) { + (p->p_flag & (P_NOSUGID|P_TRACED)) == 0) { /* * Turn off syscall tracing for set-id programs, except for * root. Record any set-id flags first to make sure that --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -584,7 +584,7 @@ * Preserve some more flags in subprocess. P_PROFIL has already * been preserved. */ - p2->p_flag |= p1->p_flag & P_SUGID; + p2->p_flag |= p1->p_flag & P_INHERITED; td2->td_pflags |= td->td_pflags & TDP_ALTSTACK; SESS_LOCK(p1->p_session); if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) --- sys/kern/vfs_syscalls.c +++ sys/kern/vfs_syscalls.c @@ -860,9 +860,12 @@ */ static int chroot_allow_open_directories = 1; +static int chroot_allow_unprivileged = 0; SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, &chroot_allow_open_directories, 0, ""); +SYSCTL_INT(_kern, OID_AUTO, chroot_allow_unprivileged, CTLFLAG_RW, + &chroot_allow_unprivileged, 0, ""); /* * Change notion of root (``/'') directory. @@ -880,12 +883,27 @@ } */ *uap; { int error; + struct proc *p; struct nameidata nd; int vfslocked; error = priv_check(td, PRIV_VFS_CHROOT); - if (error) - return (error); + if (error) { + if (!chroot_allow_unprivileged) + return (error); + + /* + * Disallow this process and its children to use setuid + * bits. Users could hardlink setuid applications into a + * chroot which contains a fake C library to obtain + * super-user privileges. + */ + p = td->td_proc; + PROC_LOCK(p); + p->p_flag |= P_NOSUGID; + PROC_UNLOCK(p); + } + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, UIO_USERSPACE, uap->path, td); error = namei(&nd); --- sys/sys/proc.h +++ sys/sys/proc.h @@ -643,7 +643,9 @@ #define P_INMEM 0x10000000 /* Loaded into memory. */ #define P_SWAPPINGOUT 0x20000000 /* Process is being swapped out. */ #define P_SWAPPINGIN 0x40000000 /* Process is being swapped in. */ +#define P_NOSUGID 0x80000000 /* Ignore set[ug]id on exec. */ +#define P_INHERITED (P_SUGID|P_NOSUGID) #define P_STOPPED (P_STOPPED_SIG|P_STOPPED_SINGLE|P_STOPPED_TRACE) #define P_SHOULDSTOP(p) ((p)->p_flag & P_STOPPED) >Release-Note: >Audit-Trail: >Unformatted: