Module Name:    src
Committed By:   riastradh
Date:           Sat Apr 22 13:54:20 UTC 2023

Modified Files:
        src/sys/rump/librump/rumpkern: Makefile.rumpkern
        src/sys/secmodel/extensions: files.extensions secmodel_extensions.c
Added Files:
        src/sys/rump/librump/rumpkern: secmodel_extensions_rump.c
        src/sys/secmodel/extensions: extensions_impl.h
            secmodel_extensions_vfs.c

Log Message:
secmodel_extensions: Split vfs part into separate .c file.

This way we can provide weak rumpkern stubs that don't require
rumpvfs for things that are relevant to vfs, but if you do link
rumpvfs then you get the same logic in secmodel extensions.


To generate a diff of this commit:
cvs rdiff -u -r1.188 -r1.189 src/sys/rump/librump/rumpkern/Makefile.rumpkern
cvs rdiff -u -r0 -r1.1 \
    src/sys/rump/librump/rumpkern/secmodel_extensions_rump.c
cvs rdiff -u -r0 -r1.1 src/sys/secmodel/extensions/extensions_impl.h \
    src/sys/secmodel/extensions/secmodel_extensions_vfs.c
cvs rdiff -u -r1.1 -r1.2 src/sys/secmodel/extensions/files.extensions
cvs rdiff -u -r1.15 -r1.16 src/sys/secmodel/extensions/secmodel_extensions.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/rump/librump/rumpkern/Makefile.rumpkern
diff -u src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.188 src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.189
--- src/sys/rump/librump/rumpkern/Makefile.rumpkern:1.188	Mon Mar 28 20:49:52 2022
+++ src/sys/rump/librump/rumpkern/Makefile.rumpkern	Sat Apr 22 13:54:19 2023
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile.rumpkern,v 1.188 2022/03/28 20:49:52 christos Exp $
+#	$NetBSD: Makefile.rumpkern,v 1.189 2023/04/22 13:54:19 riastradh Exp $
 #
 
 IOCONFDIR:=	${.PARSEDIR}
@@ -147,6 +147,7 @@ SRCS+=	uvm_page_array.c uvm_page_status.
 SRCS+=	secmodel.c
 SRCS+=	secmodel_suser.c
 SRCS+=	secmodel_extensions.c
+SRCS+=	secmodel_extensions_rump.c	# stubs
 
 # the funny bit.  this doesn't really belong here, but helps with the
 # needs of kern_descrip.c.  And since it's a fully dynamic interface,

Index: src/sys/secmodel/extensions/files.extensions
diff -u src/sys/secmodel/extensions/files.extensions:1.1 src/sys/secmodel/extensions/files.extensions:1.2
--- src/sys/secmodel/extensions/files.extensions:1.1	Sun Dec  4 19:25:00 2011
+++ src/sys/secmodel/extensions/files.extensions	Sat Apr 22 13:54:19 2023
@@ -1,5 +1,6 @@
-# $NetBSD: files.extensions,v 1.1 2011/12/04 19:25:00 jym Exp $
+# $NetBSD: files.extensions,v 1.2 2023/04/22 13:54:19 riastradh Exp $
 
 defflag secmodel_extensions
 
 file	secmodel/extensions/secmodel_extensions.c	secmodel_extensions
+file	secmodel/extensions/secmodel_extensions_vfs.c	secmodel_extensions

Index: src/sys/secmodel/extensions/secmodel_extensions.c
diff -u src/sys/secmodel/extensions/secmodel_extensions.c:1.15 src/sys/secmodel/extensions/secmodel_extensions.c:1.16
--- src/sys/secmodel/extensions/secmodel_extensions.c:1.15	Tue Mar 29 22:29:29 2022
+++ src/sys/secmodel/extensions/secmodel_extensions.c	Sat Apr 22 13:54:19 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_extensions.c,v 1.15 2022/03/29 22:29:29 christos Exp $ */
+/* $NetBSD: secmodel_extensions.c,v 1.16 2023/04/22 13:54:19 riastradh Exp $ */
 /*-
  * Copyright (c) 2011 Elad Efrat <e...@netbsd.org>
  * All rights reserved.
@@ -27,14 +27,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions.c,v 1.15 2022/03/29 22:29:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions.c,v 1.16 2023/04/22 13:54:19 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/kauth.h>
 
 #include <sys/mount.h>
-#include <sys/vnode.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
 #include <sys/proc.h>
@@ -43,20 +42,18 @@ __KERNEL_RCSID(0, "$NetBSD: secmodel_ext
 
 #include <secmodel/secmodel.h>
 #include <secmodel/extensions/extensions.h>
+#include <secmodel/extensions/extensions_impl.h>
 
 MODULE(MODULE_CLASS_SECMODEL, extensions, NULL);
 
-static int dovfsusermount;
 static int curtain;
 static int user_set_cpu_affinity;
-static int hardlink_check_uid;
-static int hardlink_check_gid;
 
 #ifdef PT_SETDBREGS
 int user_set_dbregs;
 #endif
 
-static kauth_listener_t l_system, l_process, l_network, l_vnode;
+static kauth_listener_t l_process, l_network;
 
 static secmodel_t extensions_sm;
 
@@ -65,18 +62,13 @@ static void secmodel_extensions_start(vo
 static void secmodel_extensions_stop(void);
 
 static void sysctl_security_extensions_setup(struct sysctllog **);
-static int  sysctl_extensions_user_handler(SYSCTLFN_PROTO);
 static int  sysctl_extensions_curtain_handler(SYSCTLFN_PROTO);
 static bool is_securelevel_above(int);
 
-static int secmodel_extensions_system_cb(kauth_cred_t, kauth_action_t,
-    void *, void *, void *, void *, void *);
 static int secmodel_extensions_process_cb(kauth_cred_t, kauth_action_t,
     void *, void *, void *, void *, void *);
 static int secmodel_extensions_network_cb(kauth_cred_t, kauth_action_t,
     void *, void *, void *, void *, void *);
-static int secmodel_extensions_vnode_cb(kauth_cred_t, kauth_action_t,
-    void *, void *, void *, void *, void *);
 
 SYSCTL_SETUP(sysctl_security_extensions_setup,
     "security extensions sysctl")
@@ -120,14 +112,6 @@ SYSCTL_SETUP(sysctl_security_extensions_
 
 	sysctl_createv(clog, 0, &rnode, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "usermount",
-		       SYSCTL_DESCR("Whether unprivileged users may mount "
-				    "filesystems"),
-		       sysctl_extensions_user_handler, 0, &dovfsusermount, 0,
-		       CTL_CREATE, CTL_EOL);
-
-	sysctl_createv(clog, 0, &rnode, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 		       CTLTYPE_INT, "curtain",
 		       SYSCTL_DESCR("Curtain information about objects to "\
 		       		    "users not owning them."),
@@ -154,41 +138,6 @@ SYSCTL_SETUP(sysctl_security_extensions_
 		       CTL_CREATE, CTL_EOL);
 #endif
 
-	sysctl_createv(clog, 0, &rnode, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "hardlink_check_uid",
-		       SYSCTL_DESCR("Whether unprivileged users can hardlink "\
-			    "to files they don't own"),
-		       sysctl_extensions_user_handler, 0,
-		       &hardlink_check_uid, 0,
-		       CTL_CREATE, CTL_EOL);
-
-	sysctl_createv(clog, 0, &rnode, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "hardlink_check_gid",
-		       SYSCTL_DESCR("Whether unprivileged users can hardlink "\
-			    "to files that are not in their " \
-			    "group membership"),
-		       sysctl_extensions_user_handler, 0,
-		       &hardlink_check_gid, 0,
-		       CTL_CREATE, CTL_EOL);
-
-	/* Compatibility: vfs.generic.usermount */
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT,
-		       CTLTYPE_NODE, "generic",
-		       SYSCTL_DESCR("Non-specific vfs related information"),
-		       NULL, 0, NULL, 0,
-		       CTL_VFS, VFS_GENERIC, CTL_EOL);
-
-	sysctl_createv(clog, 0, NULL, NULL,
-		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
-		       CTLTYPE_INT, "usermount",
-		       SYSCTL_DESCR("Whether unprivileged users may mount "
-				    "filesystems"),
-		       sysctl_extensions_user_handler, 0, &dovfsusermount, 0,
-		       CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL);
-
 	/* Compatibility: security.curtain */
 	sysctl_createv(clog, 0, NULL, NULL,
 		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
@@ -197,6 +146,8 @@ SYSCTL_SETUP(sysctl_security_extensions_
 		       		    "users not owning them."),
 		       sysctl_extensions_curtain_handler, 0, &curtain, 0,
 		       CTL_SECURITY, CTL_CREATE, CTL_EOL);
+
+	secmodel_extensions_vfs_sysctl(clog, rnode);
 }
 
 static int
@@ -234,7 +185,7 @@ sysctl_extensions_curtain_handler(SYSCTL
  * - setting value != 0 is not permitted when securelevel is above 0 (increase
  *   user rights).
  */
-static int
+int
 sysctl_extensions_user_handler(SYSCTLFN_ARGS)
 {
 	struct sysctlnode node;
@@ -297,24 +248,20 @@ static void
 secmodel_extensions_start(void)
 {
 
-	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
-	    secmodel_extensions_system_cb, NULL);
 	l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
 	    secmodel_extensions_process_cb, NULL);
 	l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
 	    secmodel_extensions_network_cb, NULL);
-	l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
-	    secmodel_extensions_vnode_cb, NULL);
+	secmodel_extensions_vfs_start();
 }
 
 static void
 secmodel_extensions_stop(void)
 {
 
-	kauth_unlisten_scope(l_system);
+	secmodel_extensions_vfs_stop();
 	kauth_unlisten_scope(l_process);
 	kauth_unlisten_scope(l_network);
-	kauth_unlisten_scope(l_vnode);
 }
 
 static int
@@ -358,84 +305,6 @@ extensions_modcmd(modcmd_t cmd, void *ar
 }
 
 static int
-secmodel_extensions_system_cb(kauth_cred_t cred, kauth_action_t action,
-    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
-{
-	vnode_t *vp;
-	struct vattr va;
-	struct mount *mp;
-	u_long flags;
-	int result;
-	enum kauth_system_req req;
-	int error;
-
-	req = (enum kauth_system_req)(uintptr_t)arg0;
-	result = KAUTH_RESULT_DEFER;
-
-	switch (action) {
-	case KAUTH_SYSTEM_MOUNT:
-		if (dovfsusermount == 0)
-			break;
-		switch (req) {
-		case KAUTH_REQ_SYSTEM_MOUNT_NEW:
-			vp = (vnode_t *)arg1;
-			mp = vp->v_mount;
-			flags = (u_long)arg2;
-
-			/*
-			 * Ensure that the user owns the directory onto which
-			 * the mount is attempted.
-			 */
-			vn_lock(vp, LK_SHARED | LK_RETRY);
-			error = VOP_GETATTR(vp, &va, cred);
-			VOP_UNLOCK(vp);
-			if (error)
-				break;
-
-			if (va.va_uid != kauth_cred_geteuid(cred))
-				break;
-
-			error = usermount_common_policy(mp, flags);
-			if (error)
-				break;
-
-			result = KAUTH_RESULT_ALLOW;
-
-			break;
-
-		case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
-			mp = arg1;
-
-			/* Must own the mount. */
-			if (mp->mnt_stat.f_owner == kauth_cred_geteuid(cred))
-				result = KAUTH_RESULT_ALLOW;
-
-			break;
-
-		case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
-			mp = arg1;
-			flags = (u_long)arg2;
-
-			/* Must own the mount. */
-			if (mp->mnt_stat.f_owner == kauth_cred_geteuid(cred) &&
-				usermount_common_policy(mp, flags) == 0)
-				result = KAUTH_RESULT_ALLOW;
-
-			break;
-
-		default:
-			break;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return (result);
-}
-
-static int
 secmodel_extensions_process_cb(kauth_cred_t cred, kauth_action_t action,
     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
 {
@@ -529,34 +398,3 @@ secmodel_extensions_network_cb(kauth_cre
 
 	return (result);
 }
-
-static int
-secmodel_extensions_vnode_cb(kauth_cred_t cred, kauth_action_t action,
-    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
-{
-	int error;
-	bool isroot;
-	struct vattr va;
-
-	if ((action & KAUTH_VNODE_ADD_LINK) == 0)
-		return KAUTH_RESULT_DEFER;
-
-	error = VOP_GETATTR((vnode_t *)arg0, &va, cred);
-	if (error)
-		goto checkroot;
-
-	if (hardlink_check_uid && kauth_cred_geteuid(cred) != va.va_uid)
-		goto checkroot;
-
-	if (hardlink_check_gid && kauth_cred_groupmember(cred, va.va_gid) != 0)
-		goto checkroot;
-
-	return KAUTH_RESULT_DEFER;
-checkroot:
-	error = secmodel_eval("org.netbsd.secmodel.suser", "is-root",
-	    cred, &isroot);
-	if (error || !isroot)
-		return KAUTH_RESULT_DENY;
-
-	return KAUTH_RESULT_DEFER;
-}

Added files:

Index: src/sys/rump/librump/rumpkern/secmodel_extensions_rump.c
diff -u /dev/null src/sys/rump/librump/rumpkern/secmodel_extensions_rump.c:1.1
--- /dev/null	Sat Apr 22 13:54:20 2023
+++ src/sys/rump/librump/rumpkern/secmodel_extensions_rump.c	Sat Apr 22 13:54:19 2023
@@ -0,0 +1,55 @@
+/*	$NetBSD: secmodel_extensions_rump.c,v 1.1 2023/04/22 13:54:19 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions_rump.c,v 1.1 2023/04/22 13:54:19 riastradh Exp $");
+
+#include <secmodel/extensions/extensions_impl.h>
+
+void rump_secmodel_extensions_vfs_start(void);
+void
+rump_secmodel_extensions_vfs_start(void)
+{
+}
+__weak_alias(secmodel_extensions_vfs_start,rump_secmodel_extensions_vfs_start);
+
+void rump_secmodel_extensions_vfs_stop(void);
+void
+rump_secmodel_extensions_vfs_stop(void)
+{
+}
+__weak_alias(secmodel_extensions_vfs_stop,rump_secmodel_extensions_vfs_stop);
+
+void rump_secmodel_extensions_vfs_sysctl(struct sysctllog **,
+    const struct sysctlnode *);
+void
+rump_secmodel_extensions_vfs_sysctl(struct sysctllog **clog,
+    const struct sysctlnode *rnode)
+{
+}
+__weak_alias(secmodel_extensions_vfs_sysctl,rump_secmodel_extensions_vfs_sysctl);

Index: src/sys/secmodel/extensions/extensions_impl.h
diff -u /dev/null src/sys/secmodel/extensions/extensions_impl.h:1.1
--- /dev/null	Sat Apr 22 13:54:20 2023
+++ src/sys/secmodel/extensions/extensions_impl.h	Sat Apr 22 13:54:19 2023
@@ -0,0 +1,43 @@
+/*	$NetBSD: extensions_impl.h,v 1.1 2023/04/22 13:54:19 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef	_SECMODEL_EXTENSIONS_EXTENSIONS_IMPL_H_
+#define	_SECMODEL_EXTENSIONS_EXTENSIONS_IMPL_H_
+
+struct sysctlnode;
+
+#include <sys/sysctl.h>
+
+int sysctl_extensions_user_handler(SYSCTLFN_PROTO);
+
+void secmodel_extensions_vfs_sysctl(struct sysctllog **,
+    const struct sysctlnode *);
+void secmodel_extensions_vfs_start(void);
+void secmodel_extensions_vfs_stop(void);
+
+#endif	/* _SECMODEL_EXTENSIONS_EXTENSIONS_IMPL_H_ */
Index: src/sys/secmodel/extensions/secmodel_extensions_vfs.c
diff -u /dev/null src/sys/secmodel/extensions/secmodel_extensions_vfs.c:1.1
--- /dev/null	Sat Apr 22 13:54:20 2023
+++ src/sys/secmodel/extensions/secmodel_extensions_vfs.c	Sat Apr 22 13:54:19 2023
@@ -0,0 +1,229 @@
+/*	$NetBSD: secmodel_extensions_vfs.c,v 1.1 2023/04/22 13:54:19 riastradh Exp $	*/
+
+/*-
+ * Copyright (c) 2011 Elad Efrat <e...@netbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions_vfs.c,v 1.1 2023/04/22 13:54:19 riastradh Exp $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <sys/kauth.h>
+#include <sys/vnode.h>
+
+#include <secmodel/secmodel.h>
+#include <secmodel/extensions/extensions.h>
+#include <secmodel/extensions/extensions_impl.h>
+
+static int dovfsusermount;
+static int hardlink_check_uid;
+static int hardlink_check_gid;
+
+static kauth_listener_t l_system, l_vnode;
+
+static int secmodel_extensions_system_cb(kauth_cred_t, kauth_action_t,
+    void *, void *, void *, void *, void *);
+static int secmodel_extensions_vnode_cb(kauth_cred_t, kauth_action_t,
+    void *, void *, void *, void *, void *);
+
+void
+secmodel_extensions_vfs_start(void)
+{
+
+	l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
+	    secmodel_extensions_system_cb, NULL);
+	l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
+	    secmodel_extensions_vnode_cb, NULL);
+}
+
+void
+secmodel_extensions_vfs_stop(void)
+{
+
+	kauth_unlisten_scope(l_system);
+	kauth_unlisten_scope(l_vnode);
+}
+
+void
+secmodel_extensions_vfs_sysctl(struct sysctllog **clog,
+    const struct sysctlnode *rnode)
+{
+
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "usermount",
+		       SYSCTL_DESCR("Whether unprivileged users may mount "
+				    "filesystems"),
+		       sysctl_extensions_user_handler, 0, &dovfsusermount, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "hardlink_check_uid",
+		       SYSCTL_DESCR("Whether unprivileged users can hardlink "\
+			    "to files they don't own"),
+		       sysctl_extensions_user_handler, 0,
+		       &hardlink_check_uid, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "hardlink_check_gid",
+		       SYSCTL_DESCR("Whether unprivileged users can hardlink "\
+			    "to files that are not in their " \
+			    "group membership"),
+		       sysctl_extensions_user_handler, 0,
+		       &hardlink_check_gid, 0,
+		       CTL_CREATE, CTL_EOL);
+
+	/* Compatibility: vfs.generic.usermount */
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "generic",
+		       SYSCTL_DESCR("Non-specific vfs related information"),
+		       NULL, 0, NULL, 0,
+		       CTL_VFS, VFS_GENERIC, CTL_EOL);
+
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "usermount",
+		       SYSCTL_DESCR("Whether unprivileged users may mount "
+				    "filesystems"),
+		       sysctl_extensions_user_handler, 0, &dovfsusermount, 0,
+		       CTL_VFS, VFS_GENERIC, VFS_USERMOUNT, CTL_EOL);
+}
+
+static int
+secmodel_extensions_system_cb(kauth_cred_t cred, kauth_action_t action,
+    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
+{
+	vnode_t *vp;
+	struct vattr va;
+	struct mount *mp;
+	u_long flags;
+	int result;
+	enum kauth_system_req req;
+	int error;
+
+	req = (enum kauth_system_req)(uintptr_t)arg0;
+	result = KAUTH_RESULT_DEFER;
+
+	switch (action) {
+	case KAUTH_SYSTEM_MOUNT:
+		if (dovfsusermount == 0)
+			break;
+		switch (req) {
+		case KAUTH_REQ_SYSTEM_MOUNT_NEW:
+			vp = (vnode_t *)arg1;
+			mp = vp->v_mount;
+			flags = (u_long)arg2;
+
+			/*
+			 * Ensure that the user owns the directory onto which
+			 * the mount is attempted.
+			 */
+			vn_lock(vp, LK_SHARED | LK_RETRY);
+			error = VOP_GETATTR(vp, &va, cred);
+			VOP_UNLOCK(vp);
+			if (error)
+				break;
+
+			if (va.va_uid != kauth_cred_geteuid(cred))
+				break;
+
+			error = usermount_common_policy(mp, flags);
+			if (error)
+				break;
+
+			result = KAUTH_RESULT_ALLOW;
+
+			break;
+
+		case KAUTH_REQ_SYSTEM_MOUNT_UNMOUNT:
+			mp = arg1;
+
+			/* Must own the mount. */
+			if (mp->mnt_stat.f_owner == kauth_cred_geteuid(cred))
+				result = KAUTH_RESULT_ALLOW;
+
+			break;
+
+		case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
+			mp = arg1;
+			flags = (u_long)arg2;
+
+			/* Must own the mount. */
+			if (mp->mnt_stat.f_owner == kauth_cred_geteuid(cred) &&
+				usermount_common_policy(mp, flags) == 0)
+				result = KAUTH_RESULT_ALLOW;
+
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return (result);
+}
+
+static int
+secmodel_extensions_vnode_cb(kauth_cred_t cred, kauth_action_t action,
+    void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
+{
+	int error;
+	bool isroot;
+	struct vattr va;
+
+	if ((action & KAUTH_VNODE_ADD_LINK) == 0)
+		return KAUTH_RESULT_DEFER;
+
+	error = VOP_GETATTR((vnode_t *)arg0, &va, cred);
+	if (error)
+		goto checkroot;
+
+	if (hardlink_check_uid && kauth_cred_geteuid(cred) != va.va_uid)
+		goto checkroot;
+
+	if (hardlink_check_gid && kauth_cred_groupmember(cred, va.va_gid) != 0)
+		goto checkroot;
+
+	return KAUTH_RESULT_DEFER;
+checkroot:
+	error = secmodel_eval("org.netbsd.secmodel.suser", "is-root",
+	    cred, &isroot);
+	if (error || !isroot)
+		return KAUTH_RESULT_DENY;
+
+	return KAUTH_RESULT_DEFER;
+}
+

Reply via email to