Date: Tue, 28 Jan 2003 11:22:03 +0100 (CET) From: Oliver Fromme <olli@secnetix.de> To: FreeBSD-gnats-submit@FreeBSD.org Cc: Oliver Fromme <olli@secnetix.de> Subject: kern/47586: [PATCH] fix information-leak (mounts) in jail(2) Message-ID: <200301281022.h0SAM3aP057049@lurza.secnetix.de>
next in thread | raw e-mail | index | archive | help
>Number: 47586 >Category: kern >Synopsis: [PATCH] fix information-leak (mounts) in jail(2) >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Jan 28 02:30:01 PST 2003 >Closed-Date: >Last-Modified: >Originator: Oliver Fromme <olli@secnetix.de> >Release: FreeBSD 4.7-RELEASE i386 >Organization: secnetix GmbH Co KG, http://www.secnetix.de/ >Environment: System: FreeBSD 4.7-RELEASE The patch presented in this PR affects systems using jail(2) environments. >Description: Currently, the jail(2) feature of FreeBSD has a bug: jailed processes can see all mounts. This can be a serious information leak and has been of critical concern to several ISPs that I've spoken to. A jailed user can type "mount" or "df" to see all mounts, which typically gives a good indication of who the other customers are. The patch presented is an improved variant of the patch in PR kern/26740: First, it scales much better, and second, it introduces a sysctl variable to control the behaviour. The sysctl MIB entry is named "jail.statfs_restricted". For backward compatibility (and POLA-preservation), the default value is 0, which disables the patch and causes the old behaviour. When set to 1, jailed processes will only see a single faked root mount. When set to 2, no mounts will be visible at all. This means, however, that certain programs (e.g. ls) will refuse to work. This setting might be useful for jails running server processes, but not user shells. The patch is for 4.7-RELEASE. It modifies statfs(), fstatfs() and getfsstat(). If the patch is accepted, I'm willing to write a short addition for the jail(8) manpage describing the new sysctl MIB entry. >How-To-Repeat: Set up a machine with several jails and observe that all jailed users can see all other users' mounts. >Fix: --- src/sys/sys/jail.h.orig Wed Nov 1 18:58:06 2000 +++ src/sys/sys/jail.h Mon Jan 27 16:07:54 2003 @@ -49,6 +49,7 @@ extern int jail_set_hostname_allowed; extern int jail_socket_unixiproute_only; extern int jail_sysvipc_allowed; +extern int jail_statfs_restricted; #endif /* !_KERNEL */ #endif /* !_SYS_JAIL_H_ */ --- src/sys/kern/kern_jail.c.orig Fri Aug 17 03:00:26 2001 +++ src/sys/kern/kern_jail.c Mon Jan 27 16:07:31 2003 @@ -44,6 +44,11 @@ &jail_sysvipc_allowed, 0, "Processes in jail can use System V IPC primitives"); +int jail_statfs_restricted = 0; +SYSCTL_INT(_jail, OID_AUTO, statfs_restricted, CTLFLAG_RW, + &jail_statfs_restricted, 0, + "Processes in jail are not allowed to see all mounts"); + int jail(p, uap) struct proc *p; --- src/sys/kern/vfs_syscalls.c.orig Fri Apr 26 02:46:04 2002 +++ src/sys/kern/vfs_syscalls.c Mon Jan 27 18:21:11 2003 @@ -61,6 +61,7 @@ #include <sys/proc.h> #include <sys/dirent.h> #include <sys/extattr.h> +#include <sys/jail.h> #include <machine/limits.h> #include <miscfs/union/union.h> @@ -660,6 +661,8 @@ register struct mount *mp; register struct statfs *sp; int error; + int non_su; + int fake_root; struct nameidata nd; struct statfs sb; @@ -670,13 +673,23 @@ sp = &mp->mnt_stat; NDFREE(&nd, NDF_ONLY_PNBUF); vrele(nd.ni_vp); + if ((fake_root = (p->p_prison && jail_statfs_restricted))) + if (jail_statfs_restricted >= 2) + return (ENOENT); error = VFS_STATFS(mp, sp, p); if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, 0, 0)) { + non_su = suser_xxx(p->p_ucred, 0, 0); + if (non_su || fake_root) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); - sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; + if (non_su) + sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; + if (fake_root) { + strcpy(sb.f_mntfromname, "jail"); + sb.f_mntonname[0] = '/'; + sb.f_mntonname[1] = '\0'; + } sp = &sb; } return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); @@ -704,6 +717,8 @@ struct mount *mp; register struct statfs *sp; int error; + int non_su; + int fake_root; struct statfs sb; if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) @@ -712,13 +727,23 @@ if (mp == NULL) return (EBADF); sp = &mp->mnt_stat; + if ((fake_root = (p->p_prison && jail_statfs_restricted))) + if (jail_statfs_restricted >= 2) + return (ENOENT); error = VFS_STATFS(mp, sp, p); if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, 0, 0)) { + non_su = suser_xxx(p->p_ucred, 0, 0); + if (non_su || fake_root) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); - sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; + if (non_su) + sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; + if (fake_root) { + strcpy(sb.f_mntfromname, "jail"); + sb.f_mntonname[0] = '/'; + sb.f_mntonname[1] = '\0'; + } sp = &sb; } return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); @@ -747,12 +772,22 @@ register struct statfs *sp; caddr_t sfsp; long count, maxcount, error; + int fake_root; + struct statfs sb; maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); sfsp = (caddr_t)SCARG(uap, buf); count = 0; + fake_root = (p->p_prison && jail_statfs_restricted); simple_lock(&mountlist_slock); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { + if (fake_root) { + if (jail_statfs_restricted > 1 || + strcmp(mp->mnt_stat.f_mntonname, "/") != 0) { + nmp = TAILQ_NEXT(mp, mnt_list); + continue; + } + } if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { nmp = TAILQ_NEXT(mp, mnt_list); continue; @@ -773,6 +808,13 @@ continue; } sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + if (fake_root) { + bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); + strcpy(sb.f_mntfromname, "jail"); + sb.f_mntonname[0] = '/'; + sb.f_mntonname[1] = '\0'; + sp = &sb; + } error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); if (error) { vfs_unbusy(mp, p); >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200301281022.h0SAM3aP057049>