Date: Thu, 23 Feb 2012 18:51:24 +0000 (UTC) From: Martin Matuska <mm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r232059 - in head: sys/fs/devfs sys/fs/nullfs sys/kern sys/sys usr.sbin/jail Message-ID: <201202231851.q1NIpOxH018329@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mm Date: Thu Feb 23 18:51:24 2012 New Revision: 232059 URL: http://svn.freebsd.org/changeset/base/232059 Log: To improve control over the use of mount(8) inside a jail(8), introduce a new jail parameter node with the following parameters: allow.mount.devfs: allow mounting the devfs filesystem inside a jail allow.mount.nullfs: allow mounting the nullfs filesystem inside a jail Both parameters are disabled by default (equals the behavior before devfs and nullfs in jails). Administrators have to explicitly allow mounting devfs and nullfs for each jail. The value "-1" of the devfs_ruleset parameter is removed in favor of the new allow setting. Reviewed by: jamie Suggested by: pjd MFC after: 2 weeks Modified: head/sys/fs/devfs/devfs_vfsops.c head/sys/fs/nullfs/null_vfsops.c head/sys/kern/kern_jail.c head/sys/sys/jail.h head/usr.sbin/jail/jail.8 Modified: head/sys/fs/devfs/devfs_vfsops.c ============================================================================== --- head/sys/fs/devfs/devfs_vfsops.c Thu Feb 23 18:50:19 2012 (r232058) +++ head/sys/fs/devfs/devfs_vfsops.c Thu Feb 23 18:51:24 2012 (r232059) @@ -71,7 +71,7 @@ devfs_mount(struct mount *mp) struct devfs_mount *fmp; struct vnode *rvp; struct thread *td = curthread; - int rsnum; + int injail, rsnum; if (devfs_unr == NULL) devfs_unr = new_unrhdr(0, INT_MAX, NULL); @@ -81,7 +81,11 @@ devfs_mount(struct mount *mp) if (mp->mnt_flag & MNT_ROOTFS) return (EOPNOTSUPP); + if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_DEVFS)) + return (EPERM); + rsnum = 0; + injail = jailed(td->td_ucred); if (mp->mnt_optnew != NULL) { if (vfs_filteropt(mp->mnt_optnew, devfs_opts)) @@ -89,24 +93,20 @@ devfs_mount(struct mount *mp) if (vfs_getopt(mp->mnt_optnew, "ruleset", NULL, NULL) == 0 && (vfs_scanopt(mp->mnt_optnew, "ruleset", "%d", - &rsnum) != 1 || rsnum < 0 || rsnum > 65535)) - error = EINVAL; - } + &rsnum) != 1 || rsnum < 0 || rsnum > 65535)) { + vfs_mount_error(mp, "%s", + "invalid ruleset specification"); + return (EINVAL); + } - /* jails enforce their ruleset, prison0 has no restrictions */ - if (td->td_ucred->cr_prison->pr_devfs_rsnum != 0) { - rsnum = td->td_ucred->cr_prison->pr_devfs_rsnum; - if (rsnum == -1) + if (injail && rsnum != 0 && + rsnum != td->td_ucred->cr_prison->pr_devfs_rsnum) return (EPERM); - /* check rsnum for sanity, devfs_rsnum is uint16_t */ - if (rsnum < 0 || rsnum > 65535) - error = EINVAL; } - if (error) { - vfs_mount_error(mp, "%s", "invalid ruleset specification"); - return (error); - } + /* jails enforce their ruleset */ + if (injail) + rsnum = td->td_ucred->cr_prison->pr_devfs_rsnum; if (mp->mnt_flag & MNT_UPDATE) { if (rsnum != 0) { Modified: head/sys/fs/nullfs/null_vfsops.c ============================================================================== --- head/sys/fs/nullfs/null_vfsops.c Thu Feb 23 18:50:19 2012 (r232058) +++ head/sys/fs/nullfs/null_vfsops.c Thu Feb 23 18:51:24 2012 (r232059) @@ -50,6 +50,7 @@ #include <sys/namei.h> #include <sys/proc.h> #include <sys/vnode.h> +#include <sys/jail.h> #include <fs/nullfs/null.h> @@ -75,12 +76,16 @@ nullfs_mount(struct mount *mp) struct vnode *lowerrootvp, *vp; struct vnode *nullm_rootvp; struct null_mount *xmp; + struct thread *td = curthread; char *target; int isvnunlocked = 0, len; struct nameidata nd, *ndp = &nd; NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp); + if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_NULLFS)) + return (EPERM); + if (mp->mnt_flag & MNT_ROOTFS) return (EOPNOTSUPP); /* Modified: head/sys/kern/kern_jail.c ============================================================================== --- head/sys/kern/kern_jail.c Thu Feb 23 18:50:19 2012 (r232058) +++ head/sys/kern/kern_jail.c Thu Feb 23 18:51:24 2012 (r232059) @@ -201,6 +201,8 @@ static char *pr_allow_names[] = { "allow.mount", "allow.quotas", "allow.socket_af", + "allow.mount.devfs", + "allow.mount.nullfs", }; const size_t pr_allow_names_size = sizeof(pr_allow_names); @@ -212,12 +214,14 @@ static char *pr_allow_nonames[] = { "allow.nomount", "allow.noquotas", "allow.nosocket_af", + "allow.mount.nodevfs", + "allow.mount.nonullfs", }; const size_t pr_allow_nonames_size = sizeof(pr_allow_nonames); #define JAIL_DEFAULT_ALLOW PR_ALLOW_SET_HOSTNAME #define JAIL_DEFAULT_ENFORCE_STATFS 2 -#define JAIL_DEFAULT_DEVFS_RSNUM -1 +#define JAIL_DEFAULT_DEVFS_RSNUM 0 static unsigned jail_default_allow = JAIL_DEFAULT_ALLOW; static int jail_default_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS; static int jail_default_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM; @@ -1279,7 +1283,7 @@ kern_jail_set(struct thread *td, struct pr->pr_securelevel = ppr->pr_securelevel; pr->pr_allow = JAIL_DEFAULT_ALLOW & ppr->pr_allow; pr->pr_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS; - pr->pr_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM; + pr->pr_devfs_rsnum = ppr->pr_devfs_rsnum; LIST_INIT(&pr->pr_children); mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF | MTX_DUPOK); @@ -1361,21 +1365,19 @@ kern_jail_set(struct thread *td, struct if (gotrsnum) { /* * devfs_rsnum is a uint16_t - * value of -1 disables devfs mounts */ - if (rsnum < -1 || rsnum > 65535) { + if (rsnum < 0 || rsnum > 65535) { error = EINVAL; goto done_deref_locked; } /* - * Nested jails may inherit parent's devfs ruleset - * or disable devfs + * Nested jails always inherit parent's devfs ruleset */ if (jailed(td->td_ucred)) { if (rsnum > 0 && rsnum != ppr->pr_devfs_rsnum) { error = EPERM; goto done_deref_locked; - } else if (rsnum == 0) + } else rsnum = ppr->pr_devfs_rsnum; } } @@ -1623,8 +1625,7 @@ kern_jail_set(struct thread *td, struct pr->pr_devfs_rsnum = rsnum; /* Pass this restriction on to the children. */ FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend) - if (tpr->pr_devfs_rsnum != -1) - tpr->pr_devfs_rsnum = rsnum; + tpr->pr_devfs_rsnum = rsnum; } if (name != NULL) { if (ppr == &prison0) @@ -4195,6 +4196,14 @@ SYSCTL_PROC(_security_jail, OID_AUTO, mo CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, PR_ALLOW_MOUNT, sysctl_jail_default_allow, "I", "Processes in jail can mount/unmount jail-friendly file systems"); +SYSCTL_PROC(_security_jail, OID_AUTO, mount_devfs_allowed, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + NULL, PR_ALLOW_MOUNT_DEVFS, sysctl_jail_default_allow, "I", + "Processes in jail can mount/unmount the devfs file system"); +SYSCTL_PROC(_security_jail, OID_AUTO, mount_nullfs_allowed, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + NULL, PR_ALLOW_MOUNT_NULLFS, sysctl_jail_default_allow, "I", + "Processes in jail can mount/unmount the nullfs file system"); static int sysctl_jail_default_level(SYSCTL_HANDLER_ARGS) @@ -4329,13 +4338,19 @@ SYSCTL_JAIL_PARAM(_allow, raw_sockets, C "B", "Jail may create raw sockets"); SYSCTL_JAIL_PARAM(_allow, chflags, CTLTYPE_INT | CTLFLAG_RW, "B", "Jail may alter system file flags"); -SYSCTL_JAIL_PARAM(_allow, mount, CTLTYPE_INT | CTLFLAG_RW, - "B", "Jail may mount/unmount jail-friendly file systems"); SYSCTL_JAIL_PARAM(_allow, quotas, CTLTYPE_INT | CTLFLAG_RW, "B", "Jail may set file quotas"); SYSCTL_JAIL_PARAM(_allow, socket_af, CTLTYPE_INT | CTLFLAG_RW, "B", "Jail may create sockets other than just UNIX/IPv4/IPv6/route"); +SYSCTL_JAIL_PARAM_SUBNODE(allow, mount, "Jail mount/unmount permission flags"); +SYSCTL_JAIL_PARAM(_allow_mount, , CTLTYPE_INT | CTLFLAG_RW, + "B", "Jail may mount/unmount jail-friendly file systems in general"); +SYSCTL_JAIL_PARAM(_allow_mount, devfs, CTLTYPE_INT | CTLFLAG_RW, + "B", "Jail may mount/unmount the devfs file system"); +SYSCTL_JAIL_PARAM(_allow_mount, nullfs, CTLTYPE_INT | CTLFLAG_RW, + "B", "Jail may mount/unmount the nullfs file system"); + void prison_racct_foreach(void (*callback)(struct racct *racct, void *arg2, void *arg3), void *arg2, void *arg3) Modified: head/sys/sys/jail.h ============================================================================== --- head/sys/sys/jail.h Thu Feb 23 18:50:19 2012 (r232058) +++ head/sys/sys/jail.h Thu Feb 23 18:51:24 2012 (r232059) @@ -223,7 +223,9 @@ struct prison_racct { #define PR_ALLOW_MOUNT 0x0010 #define PR_ALLOW_QUOTAS 0x0020 #define PR_ALLOW_SOCKET_AF 0x0040 -#define PR_ALLOW_ALL 0x007f +#define PR_ALLOW_MOUNT_DEVFS 0x0080 +#define PR_ALLOW_MOUNT_NULLFS 0x0100 +#define PR_ALLOW_ALL 0x01ff /* * OSD methods @@ -338,6 +340,8 @@ SYSCTL_DECL(_security_jail_param); sysctl_jail_param, fmt, descr) #define SYSCTL_JAIL_PARAM_NODE(module, descr) \ SYSCTL_NODE(_security_jail_param, OID_AUTO, module, 0, 0, descr) +#define SYSCTL_JAIL_PARAM_SUBNODE(parent, module, descr) \ + SYSCTL_NODE(_security_jail_param_##parent, OID_AUTO, module, 0, 0, descr) #define SYSCTL_JAIL_PARAM_SYS_NODE(module, access, descr) \ SYSCTL_JAIL_PARAM_NODE(module, descr); \ SYSCTL_JAIL_PARAM(_##module, , CTLTYPE_INT | (access), "E,jailsys", \ Modified: head/usr.sbin/jail/jail.8 ============================================================================== --- head/usr.sbin/jail/jail.8 Thu Feb 23 18:50:19 2012 (r232058) +++ head/usr.sbin/jail/jail.8 Thu Feb 23 18:51:24 2012 (r232059) @@ -34,7 +34,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 9, 2012 +.Dd February 23, 2012 .Dt JAIL 8 .Os .Sh NAME @@ -303,15 +303,16 @@ If the system securelevel is changed, an least as secure. .It Va devfs_ruleset The number of the devfs ruleset that is enforced for mounting devfs in -this jail and its descendants. A value of zero means no ruleset is enforced -or if set inside a jail for a descendant jail, the parent jails's devfs -ruleset enforcement is inherited. A value of -1 (default) means mounting a -devfs filesystem is not allowed. Mounting devfs inside a jail is possible -only if the +this jail. A value of zero (default) means no ruleset is enforced. Descendant +jails inherit the parent jail's devfs ruleset enforcement. Mounting devfs +inside a jail is possible only if the .Va allow.mount -permission is effective and +and +.Va allow.mount.devfs +permissions are effective and .Va enforce_statfs -is set to a value lower than 2. +is set to a value lower than 2. Devfs rules and rulesets cannot be viewed or +modified from inside a jail. .It Va children.max The number of child jails allowed to be created by this jail (or by other jails under this jail). @@ -407,6 +408,25 @@ within a jail. This permission is effective only if .Va enforce_statfs is set to a value lower than 2. +.It Va allow.mount.devfs +privileged users inside the jail will be able to mount and unmount the +devfs file system. +This permission is effective only together with +.Va allow.mount +and if +.Va enforce_statfs +is set to a value lower than 2. Please consider restricting the devfs ruleset +with the +.Va devfs_ruleset +option. +.It Va allow.mount.nullfs +privileged users inside the jail will be able to mount and unmount the +nullfs file system. +This permission is effective only together with +.Va allow.mount +and if +.Va enforce_statfs +is set to a value lower than 2. .It Va allow.quotas The prison root may administer quotas on the jail's filesystem(s). This includes filesystems that the jail may share with other jails or
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202231851.q1NIpOxH018329>