diff mbox series

[71/97] LSM: Add secmark refcounting to call_one list

Message ID 20190228224356.2608-2-casey@schaufler-ca.com (mailing list archive)
State New, archived
Headers show
Series LSM: Complete module stacking | expand

Commit Message

Casey Schaufler Feb. 28, 2019, 10:43 p.m. UTC
Add secmark_refcount_dec and secmark_refcount_inc to the
LSM hooks for which only the designated module is called.
This is in support of consistant secmark behavior.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
 include/linux/lsm_hooks.h |  2 ++
 security/security.c       | 42 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 42 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index e76e5cd05180..4020e13f0669 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2029,6 +2029,8 @@  struct lsm_one_hooks {
 	union security_list_options secctx_to_secid;
 	union security_list_options socket_getpeersec_stream;
 	union security_list_options secmark_relabel_packet;
+	union security_list_options secmark_refcount_inc;
+	union security_list_options secmark_refcount_dec;
 };
 
 /*
diff --git a/security/security.c b/security/security.c
index 024601db215e..af3f6a89ee88 100644
--- a/security/security.c
+++ b/security/security.c
@@ -472,6 +472,12 @@  void __init security_add_hooks(struct security_hook_list *hooks, int count,
 		else if (hooks[i].head ==
 				&security_hook_heads.secmark_relabel_packet)
 			lsm_base_one.secmark_relabel_packet = hooks[i].hook;
+		else if (hooks[i].head ==
+				&security_hook_heads.secmark_refcount_inc)
+			lsm_base_one.secmark_refcount_inc = hooks[i].hook;
+		else if (hooks[i].head ==
+				&security_hook_heads.secmark_refcount_dec)
+			lsm_base_one.secmark_refcount_dec = hooks[i].hook;
 		else
 			continue;
 		if (lsm_base_one.lsm == NULL)
@@ -752,6 +758,14 @@  int lsm_superblock_alloc(struct super_block *sb)
 	RC;							\
 })
 
+#define call_one_void_hook(FUNC, ...) ({			\
+	struct lsm_one_hooks *LOH = current_cred()->security;	\
+	if (LOH->FUNC.FUNC)					\
+		LOH->FUNC.FUNC(__VA_ARGS__);			\
+	else if (LOH->lsm == NULL && lsm_base_one.FUNC.FUNC)	\
+		lsm_base_one.FUNC.FUNC(__VA_ARGS__);		\
+})
+
 #define call_one_int_hook(FUNC, IRC, ...) ({			\
 	int RC = IRC;						\
 	struct lsm_one_hooks *LOH = current_cred()->security;	\
@@ -2022,6 +2036,8 @@  int security_setprocattr(const char *lsm, const char *name, void *value,
 		union security_list_options secctx_to_secid;
 		union security_list_options socket_getpeersec_stream;
 		union security_list_options secmark_relabel_packet;
+		union security_list_options secmark_refcount_inc;
+		union security_list_options secmark_refcount_dec;
 
 		if (size == 0 || size >= 100)
 			return -EINVAL;
@@ -2068,6 +2084,28 @@  int security_setprocattr(const char *lsm, const char *name, void *value,
 				break;
 			}
 		}
+		secmark_refcount_inc.secmark_refcount_inc = NULL;
+		hlist_for_each_entry(hp,
+				&security_hook_heads.secmark_refcount_inc,
+				     list) {
+			if (size >= strlen(hp->lsm) &&
+			    !strncmp(value, hp->lsm, size)) {
+				secmark_refcount_inc = hp->hook;
+				found = true;
+				break;
+			}
+		}
+		secmark_refcount_dec.secmark_refcount_dec = NULL;
+		hlist_for_each_entry(hp,
+				&security_hook_heads.secmark_refcount_dec,
+				     list) {
+			if (size >= strlen(hp->lsm) &&
+			    !strncmp(value, hp->lsm, size)) {
+				secmark_refcount_dec = hp->hook;
+				found = true;
+				break;
+			}
+		}
 		if (!found)
 			return -EINVAL;
 
@@ -2339,13 +2377,13 @@  EXPORT_SYMBOL(security_secmark_relabel_packet);
 
 void security_secmark_refcount_inc(void)
 {
-	call_void_hook(secmark_refcount_inc);
+	call_one_void_hook(secmark_refcount_inc);
 }
 EXPORT_SYMBOL(security_secmark_refcount_inc);
 
 void security_secmark_refcount_dec(void)
 {
-	call_void_hook(secmark_refcount_dec);
+	call_one_void_hook(secmark_refcount_dec);
 }
 EXPORT_SYMBOL(security_secmark_refcount_dec);