- Add usermount_common_policy() that implements some common (everything
but access control) user mounting policies: enforced MNT_NOSUID and MNT_NODEV, no MNT_EXPORT, MNT_EXEC propagation. This can be useful for secmodels that are interested in simply adding finer grained user mount support. - Add a mount subsystem listener for KAUTH_REQ_SYSTEM_MOUNT_GET.
This commit is contained in:
parent
94ebcd4993
commit
4c9fcb77c3
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vfs_init.c,v 1.44 2009/05/03 21:25:44 elad Exp $ */
|
||||
/* $NetBSD: vfs_init.c,v 1.45 2009/10/05 04:20:13 elad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -67,7 +67,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.44 2009/05/03 21:25:44 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.45 2009/10/05 04:20:13 elad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
|
@ -83,6 +83,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_init.c,v 1.44 2009/05/03 21:25:44 elad Exp $");
|
|||
#include <sys/module.h>
|
||||
#include <sys/dirhash.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/kauth.h>
|
||||
|
||||
/*
|
||||
* Sigh, such primitive tools are these...
|
||||
|
@ -119,6 +120,8 @@ const struct vnodeopv_desc * const vfs_special_vnodeopv_descs[] = {
|
|||
struct vfs_list_head vfs_list = /* vfs list */
|
||||
LIST_HEAD_INITIALIZER(vfs_list);
|
||||
|
||||
static kauth_listener_t mount_listener;
|
||||
|
||||
/*
|
||||
* This code doesn't work if the defn is **vnodop_defns with cc.
|
||||
* The problem is because of the compiler sometimes putting in an
|
||||
|
@ -331,6 +334,56 @@ vfs_op_check(void)
|
|||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Common routine to check if an unprivileged mount is allowed.
|
||||
*
|
||||
* We export just this part (i.e., without the access control) so that if a
|
||||
* secmodel wants to implement finer grained user mounts it can do so without
|
||||
* copying too much code. More elaborate policies (i.e., specific users allowed
|
||||
* to also create devices and/or introduce set-id binaries, or export
|
||||
* file-systems) will require a different implementation.
|
||||
*
|
||||
* This routine is intended to be called from listener context, and as such
|
||||
* does not take credentials as an argument.
|
||||
*/
|
||||
int
|
||||
usermount_common_policy(struct mount *mp, u_long flags)
|
||||
{
|
||||
|
||||
/* No exporting if unprivileged. */
|
||||
if (flags & MNT_EXPORTED)
|
||||
return EPERM;
|
||||
|
||||
/* Must have 'nosuid' and 'nodev'. */
|
||||
if ((flags & MNT_NODEV) == 0 || (flags & MNT_NOSUID) == 0)
|
||||
return EPERM;
|
||||
|
||||
/* Retain 'noexec'. */
|
||||
if ((mp->mnt_flag & MNT_NOEXEC) && (flags & MNT_NOEXEC) == 0)
|
||||
return EPERM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mount_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
|
||||
void *arg0, void *arg1, void *arg2, void *arg3)
|
||||
{
|
||||
int result;
|
||||
enum kauth_system_req req;
|
||||
|
||||
result = KAUTH_RESULT_DEFER;
|
||||
req = (enum kauth_system_req)arg0;
|
||||
|
||||
if ((action != KAUTH_SYSTEM_MOUNT) ||
|
||||
(req != KAUTH_REQ_SYSTEM_MOUNT_GET))
|
||||
return result;
|
||||
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the vnode structures and initialize each file system type.
|
||||
*/
|
||||
|
@ -382,6 +435,9 @@ vfsinit(void)
|
|||
*/
|
||||
vfs_hooks_init();
|
||||
|
||||
mount_listener = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
|
||||
mount_listener_cb, NULL);
|
||||
|
||||
/*
|
||||
* Establish each file system which was statically
|
||||
* included in the kernel.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: secmodel_suser.c,v 1.26 2009/10/03 03:59:39 elad Exp $ */
|
||||
/* $NetBSD: secmodel_suser.c,v 1.27 2009/10/05 04:20:13 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_suser.c,v 1.26 2009/10/03 03:59:39 elad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.27 2009/10/05 04:20:13 elad Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -152,7 +152,6 @@ void
|
|||
secmodel_suser_init(void)
|
||||
{
|
||||
secmodel_suser_curtain = 0;
|
||||
dovfsusermount = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -303,82 +302,71 @@ secmodel_suser_system_cb(kauth_cred_t cred, kauth_action_t action,
|
|||
|
||||
break;
|
||||
|
||||
case KAUTH_SYSTEM_FS_RESERVEDSPACE:
|
||||
if (isroot)
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
break;
|
||||
|
||||
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;
|
||||
case KAUTH_REQ_SYSTEM_MOUNT_NEW: {
|
||||
struct mount *mp = ((struct vnode *)arg1)->v_mount;
|
||||
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;
|
||||
|
||||
if (isroot) {
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dovfsusermount)
|
||||
break;
|
||||
|
||||
if (usermount_common_policy(mp, flags) != 0)
|
||||
break;
|
||||
|
||||
case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
|
||||
if (isroot)
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
else {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT: {
|
||||
struct mount *mp = arg1;
|
||||
|
||||
if (mp->mnt_stat.f_owner ==
|
||||
kauth_cred_geteuid(cred))
|
||||
if (isroot) {
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dovfsusermount)
|
||||
break;
|
||||
|
||||
/* Must own the mount. */
|
||||
if (mp->mnt_stat.f_owner != kauth_cred_geteuid(cred))
|
||||
break;
|
||||
|
||||
case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
|
||||
if (isroot)
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
else if (dovfsusermount) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: {
|
||||
struct mount *mp = arg1;
|
||||
u_long flags = (u_long)arg2;
|
||||
|
||||
/* No exporting for non-root. */
|
||||
if (flags & MNT_EXPORTED)
|
||||
if (isroot) {
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dovfsusermount)
|
||||
break;
|
||||
|
||||
if (!(flags & MNT_NODEV) ||
|
||||
!(flags & MNT_NOSUID))
|
||||
/* Must own the mount. */
|
||||
if (mp->mnt_stat.f_owner != kauth_cred_geteuid(cred))
|
||||
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))
|
||||
if (usermount_common_policy(mp, flags) != 0)
|
||||
break;
|
||||
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -444,6 +432,7 @@ secmodel_suser_system_cb(kauth_cred_t cred, kauth_action_t action,
|
|||
case KAUTH_SYSTEM_MKNOD:
|
||||
case KAUTH_SYSTEM_SETIDCORE:
|
||||
case KAUTH_SYSTEM_MODULE:
|
||||
case KAUTH_SYSTEM_FS_RESERVEDSPACE:
|
||||
if (isroot)
|
||||
result = KAUTH_RESULT_ALLOW;
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mount.h,v 1.191 2009/07/18 16:31:43 reinoud Exp $ */
|
||||
/* $NetBSD: mount.h,v 1.192 2009/10/05 04:20:13 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1991, 1993
|
||||
|
@ -433,6 +433,8 @@ void mount_finispecific(struct mount *);
|
|||
void * mount_getspecific(struct mount *, specificdata_key_t);
|
||||
void mount_setspecific(struct mount *, specificdata_key_t, void *);
|
||||
|
||||
int usermount_common_policy(struct mount *, u_long);
|
||||
|
||||
LIST_HEAD(vfs_list_head, vfsops);
|
||||
extern struct vfs_list_head vfs_list;
|
||||
|
||||
|
|
Loading…
Reference in New Issue