Module Name: src
Committed By: christos
Date: Sun Mar 27 16:28:35 UTC 2022
Modified Files:
src/sys/secmodel/extensions: secmodel_extensions.c
Log Message:
Implement restrictions for adding hard links to files
To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 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/secmodel/extensions/secmodel_extensions.c
diff -u src/sys/secmodel/extensions/secmodel_extensions.c:1.12 src/sys/secmodel/extensions/secmodel_extensions.c:1.13
--- src/sys/secmodel/extensions/secmodel_extensions.c:1.12 Mon Mar 16 17:20:12 2020
+++ src/sys/secmodel/extensions/secmodel_extensions.c Sun Mar 27 12:28:35 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_extensions.c,v 1.12 2020/03/16 21:20:12 pgoyette Exp $ */
+/* $NetBSD: secmodel_extensions.c,v 1.13 2022/03/27 16:28:35 christos Exp $ */
/*-
* Copyright (c) 2011 Elad Efrat <[email protected]>
* All rights reserved.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions.c,v 1.12 2020/03/16 21:20:12 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_extensions.c,v 1.13 2022/03/27 16:28:35 christos Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -49,12 +49,14 @@ MODULE(MODULE_CLASS_SECMODEL, extensions
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;
+static kauth_listener_t l_system, l_process, l_network, l_vnode;
static secmodel_t extensions_sm;
@@ -73,6 +75,8 @@ static int secmodel_extensions_process_c
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")
@@ -150,6 +154,25 @@ 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 they that they 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,
@@ -280,6 +303,8 @@ secmodel_extensions_start(void)
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);
}
static void
@@ -289,6 +314,7 @@ secmodel_extensions_stop(void)
kauth_unlisten_scope(l_system);
kauth_unlisten_scope(l_process);
kauth_unlisten_scope(l_network);
+ kauth_unlisten_scope(l_vnode);
}
static int
@@ -503,3 +529,33 @@ 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, 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;
+}