diff --git a/share/examples/secmodel/secmodel_example.c b/share/examples/secmodel/secmodel_example.c index c0e9db981a95..cc96c18de1d3 100644 --- a/share/examples/secmodel/secmodel_example.c +++ b/share/examples/secmodel/secmodel_example.c @@ -1,4 +1,4 @@ -/* $NetBSD: secmodel_example.c,v 1.10 2006/12/26 10:43:43 elad Exp $ */ +/* $NetBSD: secmodel_example.c,v 1.11 2007/01/02 10:47:29 elad Exp $ */ /* * This file is placed in the public domain. @@ -13,7 +13,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: secmodel_example.c,v 1.10 2006/12/26 10:43:43 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: secmodel_example.c,v 1.11 2007/01/02 10:47:29 elad Exp $"); #include #include @@ -138,6 +138,18 @@ secmodel_example_system_cb(kauth_cred_t cred, kauth_action_t action, req = (enum kauth_system_req)arg0; switch (action) { + case KAUTH_SYSTEM_MOUNT: + switch (req) { + case KAUTH_REQ_SYSTEM_MOUNT_GET: + case KAUTH_REQ_SYSTEM_MOUNT_NEW: + case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT: + case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: + default: + result = KAUTH_RESULT_DEFER; + break; + } + break; + case KAUTH_SYSTEM_TIME: switch (req) { case KAUTH_REQ_SYSTEM_TIME_ADJTIME: diff --git a/share/man/man9/kauth.9 b/share/man/man9/kauth.9 index bc27c8f66020..84e9e9319f4b 100644 --- a/share/man/man9/kauth.9 +++ b/share/man/man9/kauth.9 @@ -1,4 +1,4 @@ -.\" $NetBSD: kauth.9,v 1.44 2007/01/01 23:33:03 elad Exp $ +.\" $NetBSD: kauth.9,v 1.45 2007/01/02 10:47:29 elad Exp $ .\" .\" Copyright (c) 2005, 2006 Elad Efrat .\" All rights reserved. @@ -28,7 +28,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd January 1, 2007 +.Dd January 2, 2007 .Dt KAUTH 9 .Os .Sh NAME @@ -194,6 +194,60 @@ Check if an LKM request is allowed. is the command. .It Dv KAUTH_SYSTEM_MKNOD Check if creating devices is allowed. +.It Dv KAUTH_SYSTEM_MOUNT +Check if mount-related operations are allowed. +.Pp +.Ar req +can be any of the following: +.Bl -tag +.It Dv KAUTH_REQ_SYSTEM_MOUNT_GET +Check if retrieving information about a mount is allowed. +.Ar arg1 +is a +.Ft struct mount * +with the mount structure in question, +.Ar arg2 +is a +.Ft void * +with file-system specific data, if any. +.It Dv KAUTH_REQ_SYSTEM_MOUNT_NEW +Check if mounting a new file-system is allowed. +.Pp +.Ar arg1 +is the +.Ft struct vnode * +on which the file-system is to be mounted, +.Ar arg2 +is an +.Ft int +with the mount flags, and +.Ar arg3 +is a +.Ft void * +with file-system specific data, if any. +.It Dv KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT +Checks if unmounting a file-system is allowed. +.Pp +.Ar arg1 +is a +.Ft struct mount * +with the mount in question. +.It Dv KAUTH_REQ_SYSTEM_MOUNT_UPDATE +Checks if updating an existing mount is allowed. +.Pp +.Ar arg1 +is the +.Ft struct mount * +of the existing mount, +.Ar arg2 +is an +.Ft int +with the new mount flags, and +.Ar arg3 +is a +.Ft void * +with file-system specific data, if any. +.El .It Dv KAUTH_SYSTEM_REBOOT Check if rebooting is allowed. .It Dv KAUTH_SYSTEM_SETIDCORE diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 9d64c56def61..1c9c2d93c0da 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_syscalls.c,v 1.291 2007/01/01 22:00:16 pooka Exp $ */ +/* $NetBSD: vfs_syscalls.c,v 1.292 2007/01/02 10:47:29 elad Exp $ */ /* * Copyright (c) 1989, 1993 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.291 2007/01/01 22:00:16 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.292 2007/01/02 10:47:29 elad Exp $"); #include "opt_compat_netbsd.h" #include "opt_compat_43.h" @@ -170,39 +170,12 @@ mount_update(struct lwp *l, struct vnode *vp, const char *path, int flags, error = EOPNOTSUPP; /* Needs translation */ goto out; } - /* - * In "highly secure" mode, don't let the caller do anything - * but downgrade a filesystem from read-write to read-only. - */ - if (securelevel >= 2 && - flags != - (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD | MNT_FORCE | MNT_UPDATE)) { - error = EPERM; + + error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, + KAUTH_REQ_SYSTEM_MOUNT_UPDATE, mp, KAUTH_ARG(flags), data); + if (error) goto out; - } - /* - * Only root, or the user that did the original mount is - * permitted to update it. - */ - if (mp->mnt_stat.f_owner != kauth_cred_geteuid(l->l_cred) && - (error = kauth_authorize_generic(l->l_cred, - KAUTH_GENERIC_ISSUSER, NULL)) != 0) { - goto out; - } - /* - * Do not allow NFS export by non-root users. For non-root - * users, silently enforce MNT_NOSUID and MNT_NODEV, and - * MNT_NOEXEC if mount point is already MNT_NOEXEC. - */ - if (kauth_cred_geteuid(l->l_cred) != 0) { - if (flags & MNT_EXPORTED) { - error = EPERM; - goto out; - } - flags |= MNT_NOSUID | MNT_NODEV; - if (saved_flags & MNT_NOEXEC) - flags |= MNT_NOEXEC; - } + if (vfs_busy(mp, LK_NOWAIT, 0)) { error = EPERM; goto out; @@ -273,9 +246,9 @@ mount_domount(struct lwp *l, struct vnode *vp, const char *fstype, char fstypename[MFSNAMELEN]; int error; - /* XXX secmodel stuff. */ - if (securelevel >= 2) { - error = EPERM; + error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, + KAUTH_REQ_SYSTEM_MOUNT_NEW, vp, KAUTH_ARG(flags), data); + if (error) { vput(vp); goto out; } @@ -305,16 +278,6 @@ mount_domount(struct lwp *l, struct vnode *vp, const char *fstype, goto out; } - /* - * For non-root users, silently enforce MNT_NOSUID and MNT_NODEV. - * Also propagate MNT_NOEXEC. - */ - if (kauth_cred_geteuid(l->l_cred) != 0) { - flags |= MNT_NOSUID | MNT_NODEV; - if (vp->v_mount->mnt_flag & MNT_NOEXEC) - flags |= MNT_NOEXEC; - } - /* * Copy file-system type from userspace. */ @@ -442,6 +405,12 @@ mount_getargs(struct lwp *l, struct vnode *vp, const char *path, int flags, mp = vp->v_mount; + /* XXX: probably some notion of "can see" here if we want isolation. */ + error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, + KAUTH_REQ_SYSTEM_MOUNT_GET, mp, data, NULL); + if (error) + goto out; + if ((vp->v_flag & VROOT) == 0) { error = EINVAL; goto out; @@ -476,12 +445,6 @@ sys_mount(struct lwp *l, void *v, register_t *retval) struct nameidata nd; int error; - /* XXX secmodel stuff. */ - if (dovfsusermount == 0 && (SCARG(uap, flags) & MNT_GETARGS) == 0 && - (error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, - &l->l_acflag))) - return (error); - /* * Get vnode to be covered */ diff --git a/sys/secmodel/bsd44/secmodel_bsd44_securelevel.c b/sys/secmodel/bsd44/secmodel_bsd44_securelevel.c index 3d5ae15b60ec..0e77fbe5343b 100644 --- a/sys/secmodel/bsd44/secmodel_bsd44_securelevel.c +++ b/sys/secmodel/bsd44/secmodel_bsd44_securelevel.c @@ -1,4 +1,4 @@ -/* $NetBSD: secmodel_bsd44_securelevel.c,v 1.21 2006/12/31 10:38:18 elad Exp $ */ +/* $NetBSD: secmodel_bsd44_securelevel.c,v 1.22 2007/01/02 10:47:29 elad Exp $ */ /*- * Copyright (c) 2006 Elad Efrat * All rights reserved. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_securelevel.c,v 1.21 2006/12/31 10:38:18 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_securelevel.c,v 1.22 2007/01/02 10:47:29 elad Exp $"); #ifdef _KERNEL_OPT #include "opt_insecure.h" @@ -170,6 +170,37 @@ secmodel_bsd44_securelevel_system_cb(kauth_cred_t cred, result = KAUTH_RESULT_ALLOW; break; + case KAUTH_SYSTEM_MOUNT: + switch (req) { + case KAUTH_REQ_SYSTEM_MOUNT_NEW: + if (securelevel > 1) + break; + + result = KAUTH_RESULT_ALLOW; + break; + + case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: + if (securelevel > 1) { + struct mount *mp = arg1; + u_long flags = (u_long)arg2; + + /* Can only degrade from read/write to read-only. */ + if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD | + MNT_FORCE | MNT_UPDATE)) + break; + } + + result = KAUTH_RESULT_ALLOW; + + break; + + default: + result = KAUTH_RESULT_DEFER; + break; + } + + break; + case KAUTH_SYSTEM_SYSCTL: switch (req) { case KAUTH_REQ_SYSTEM_SYSCTL_ADD: diff --git a/sys/secmodel/bsd44/secmodel_bsd44_suser.c b/sys/secmodel/bsd44/secmodel_bsd44_suser.c index 53cb7ef5b674..494a30f9c204 100644 --- a/sys/secmodel/bsd44/secmodel_bsd44_suser.c +++ b/sys/secmodel/bsd44/secmodel_bsd44_suser.c @@ -1,4 +1,4 @@ -/* $NetBSD: secmodel_bsd44_suser.c,v 1.23 2006/12/27 10:02:46 elad Exp $ */ +/* $NetBSD: secmodel_bsd44_suser.c,v 1.24 2007/01/02 10:47:29 elad Exp $ */ /*- * Copyright (c) 2006 Elad Efrat * All rights reserved. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.23 2006/12/27 10:02:46 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.24 2007/01/02 10:47:29 elad Exp $"); #include #include @@ -60,6 +60,8 @@ __KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.23 2006/12/27 10:02:46 el #include +extern int dovfsusermount; + void secmodel_bsd44_suser_start(void) { @@ -138,6 +140,83 @@ secmodel_bsd44_suser_system_cb(kauth_cred_t cred, kauth_action_t action, req = (enum kauth_system_req)arg0; switch (action) { + case KAUTH_SYSTEM_MOUNT: + switch (req) { + case KAUTH_REQ_SYSTEM_MOUNT_GET: + result = KAUTH_RESULT_ALLOW; + break; + + case KAUTH_REQ_SYSTEM_MOUNT_NEW: + if (isroot) + result = KAUTH_RESULT_ALLOW; + else if (dovfsusermount) { + struct vnode *vp = arg1; + u_long flags = (u_long)arg2; + + if (!(flags & MNT_NODEV) || + !(flags & MNT_NOSUID)) + break; + + if ((vp->v_mount->mnt_flag & MNT_NOEXEC) && + !(flags & MNT_NOEXEC)) + break; + + result = KAUTH_RESULT_ALLOW; + } + + break; + + case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT: + if (isroot) + result = KAUTH_RESULT_ALLOW; + else { + struct mount *mp = arg1; + + if (mp->mnt_stat.f_owner == + kauth_cred_geteuid(cred)) + result = KAUTH_RESULT_ALLOW; + } + + break; + + case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: + if (isroot) + result = KAUTH_RESULT_ALLOW; + else if (dovfsusermount) { + struct mount *mp = arg1; + u_long flags = (u_long)arg2; + + /* No exporting for non-root. */ + if (flags & MNT_EXPORTED) + break; + + if (!(flags & MNT_NODEV) || + !(flags & MNT_NOSUID)) + break; + + /* + * Only super-user, or user that did the mount, + * can update. + */ + if (mp->mnt_stat.f_owner != + kauth_cred_geteuid(cred)) + break; + + /* Retain 'noexec'. */ + if ((mp->mnt_flag & MNT_NOEXEC) && + !(flags & MNT_NOEXEC)) + break; + + result = KAUTH_RESULT_ALLOW; + } + + break; + + default: + result = KAUTH_RESULT_DEFER; + break; + } + case KAUTH_SYSTEM_TIME: switch (req) { case KAUTH_REQ_SYSTEM_TIME_ADJTIME: diff --git a/sys/sys/kauth.h b/sys/sys/kauth.h index 29d21d14495b..ad0c38fde6cb 100644 --- a/sys/sys/kauth.h +++ b/sys/sys/kauth.h @@ -1,4 +1,4 @@ -/* $NetBSD: kauth.h,v 1.29 2006/12/26 10:43:44 elad Exp $ */ +/* $NetBSD: kauth.h,v 1.30 2007/01/02 10:47:28 elad Exp $ */ /*- * Copyright (c) 2005, 2006 Elad Efrat @@ -87,6 +87,7 @@ enum { KAUTH_SYSTEM_FILEHANDLE, KAUTH_SYSTEM_LKM, KAUTH_SYSTEM_MKNOD, + KAUTH_SYSTEM_MOUNT, KAUTH_SYSTEM_REBOOT, KAUTH_SYSTEM_SETIDCORE, KAUTH_SYSTEM_SWAPCTL, @@ -101,6 +102,10 @@ enum kauth_system_req { KAUTH_REQ_SYSTEM_CHROOT_CHROOT=1, KAUTH_REQ_SYSTEM_CHROOT_FCHROOT, KAUTH_REQ_SYSTEM_DEBUG_IPKDB, + KAUTH_REQ_SYSTEM_MOUNT_GET, + KAUTH_REQ_SYSTEM_MOUNT_NEW, + KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT, + KAUTH_REQ_SYSTEM_MOUNT_UPDATE, KAUTH_REQ_SYSTEM_SYSCTL_ADD, KAUTH_REQ_SYSTEM_SYSCTL_DELETE, KAUTH_REQ_SYSTEM_SYSCTL_DESC,