Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys - Add usermount_common_policy() that implements some com...
details: https://anonhg.NetBSD.org/src/rev/d487456e69ae
branches: trunk
changeset: 747900:d487456e69ae
user: elad <elad%NetBSD.org@localhost>
date: Mon Oct 05 04:20:13 2009 +0000
description:
- 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.
diffstat:
sys/kern/vfs_init.c | 60 +++++++++++++++++-
sys/secmodel/suser/secmodel_suser.c | 117 ++++++++++++++++-------------------
sys/sys/mount.h | 4 +-
3 files changed, 114 insertions(+), 67 deletions(-)
diffs (288 lines):
diff -r ba456a76da2d -r d487456e69ae sys/kern/vfs_init.c
--- a/sys/kern/vfs_init.c Mon Oct 05 03:54:17 2009 +0000
+++ b/sys/kern/vfs_init.c Mon Oct 05 04:20:13 2009 +0000
@@ -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 @@
#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 @@
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
@@ -332,6 +335,56 @@
#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.
*/
void
@@ -382,6 +435,9 @@
*/
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.
diff -r ba456a76da2d -r d487456e69ae sys/secmodel/suser/secmodel_suser.c
--- a/sys/secmodel/suser/secmodel_suser.c Mon Oct 05 03:54:17 2009 +0000
+++ b/sys/secmodel/suser/secmodel_suser.c Mon Oct 05 04:20:13 2009 +0000
@@ -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@localhost>
* 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 @@
secmodel_suser_init(void)
{
secmodel_suser_curtain = 0;
- dovfsusermount = 0;
}
void
@@ -303,83 +302,72 @@
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: {
+ struct mount *mp = ((struct vnode *)arg1)->v_mount;
+ u_long flags = (u_long)arg2;
- case KAUTH_REQ_SYSTEM_MOUNT_NEW:
- if (isroot)
+ if (isroot) {
result = KAUTH_RESULT_ALLOW;
- else if (dovfsusermount) {
- struct vnode *vp = arg1;
- u_long flags = (u_long)arg2;
+ break;
+ }
+
+ if (!dovfsusermount)
+ break;
+
+ if (usermount_common_policy(mp, flags) != 0)
+ break;
- if (!(flags & MNT_NODEV) ||
- !(flags & MNT_NOSUID))
- break;
+ result = KAUTH_RESULT_ALLOW;
+
+ break;
+ }
+
+ case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT: {
+ struct mount *mp = arg1;
- if ((vp->v_mount->mnt_flag & MNT_NOEXEC) &&
- !(flags & MNT_NOEXEC))
- break;
+ if (isroot) {
+ result = KAUTH_RESULT_ALLOW;
+ break;
+ }
- result = KAUTH_RESULT_ALLOW;
- }
+ if (!dovfsusermount)
+ break;
+
+ /* Must own the mount. */
+ if (mp->mnt_stat.f_owner != kauth_cred_geteuid(cred))
+ break;
+
+ result = KAUTH_RESULT_ALLOW;
break;
+ }
- case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
- if (isroot)
+ case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: {
+ struct mount *mp = arg1;
+ u_long flags = (u_long)arg2;
+
+ if (isroot) {
result = KAUTH_RESULT_ALLOW;
- else {
- struct mount *mp = arg1;
+ break;
+ }
+
+ if (!dovfsusermount)
+ break;
- if (mp->mnt_stat.f_owner ==
- kauth_cred_geteuid(cred))
- result = KAUTH_RESULT_ALLOW;
- }
+ /* Must own the mount. */
+ if (mp->mnt_stat.f_owner != kauth_cred_geteuid(cred))
+ break;
+
+ if (usermount_common_policy(mp, flags) != 0)
+ break;
+
+ 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:
break;
}
@@ -444,6 +432,7 @@
case KAUTH_SYSTEM_MKNOD:
case KAUTH_SYSTEM_SETIDCORE:
case KAUTH_SYSTEM_MODULE:
+ case KAUTH_SYSTEM_FS_RESERVEDSPACE:
if (isroot)
result = KAUTH_RESULT_ALLOW;
break;
diff -r ba456a76da2d -r d487456e69ae sys/sys/mount.h
--- a/sys/sys/mount.h Mon Oct 05 03:54:17 2009 +0000
+++ b/sys/sys/mount.h Mon Oct 05 04:20:13 2009 +0000
@@ -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_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;
Home |
Main Index |
Thread Index |
Old Index