Make mount(2) and unmount(2) use kauth(9) for security policy.

Okay yamt@.
This commit is contained in:
elad 2007-01-02 10:47:28 +00:00
parent 6047a69a6e
commit a13160f423
6 changed files with 206 additions and 62 deletions

View File

@ -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 <sys/cdefs.h>
__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 <sys/types.h>
#include <sys/param.h>
@ -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:

View File

@ -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 <elad@NetBSD.org>
.\" 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

View File

@ -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 <sys/cdefs.h>
__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
*/

View File

@ -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 <elad@NetBSD.org>
* All rights reserved.
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__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:

View File

@ -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 <elad@NetBSD.org>
* All rights reserved.
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__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 <sys/types.h>
#include <sys/param.h>
@ -60,6 +60,8 @@ __KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.23 2006/12/27 10:02:46 el
#include <secmodel/bsd44/suser.h>
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:

View File

@ -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 <elad@NetBSD.org>
@ -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,