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; +} +