Inter-revision diff: patch 2

Comparing v1 (message) to v28 (message)

--- v1
+++ v28
@@ -1,945 +1,941 @@
-Move management of the sock->sk_security blob out
-of the individual security modules and into the security
-infrastructure. Instead of allocating the blobs from within
-the modules the modules tell the infrastructure how much
-space is required, and the space is allocated there.
+When more than one security module is exporting data to
+audit and networking sub-systems a single 32 bit integer
+is no longer sufficient to represent the data. Add a
+structure to be used instead.
 
+The lsmblob structure is currently an array of
+u32 "secids". There is an entry for each of the
+security modules built into the system that would
+use secids if active. The system assigns the module
+a "slot" when it registers hooks. If modules are
+compiled in but not registered there will be unused
+slots.
+
+A new lsm_id structure, which contains the name
+of the LSM and its slot number, is created. There
+is an instance for each LSM, which assigns the name
+and passes it to the infrastructure to set the slot.
+
+The audit rules data is expanded to use an array of
+security module data rather than a single instance.
+Because IMA uses the audit rule functions it is
+affected as well.
+
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
+Acked-by: Paul Moore <paul@paul-moore.com>
+Acked-by: John Johansen <john.johansen@canonical.com>
 Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
+Cc: <bpf@vger.kernel.org>
+Cc: linux-audit@redhat.com
+Cc: linux-security-module@vger.kernel.org
+Cc: selinux@vger.kernel.org
+To: Mimi Zohar <zohar@linux.ibm.com>
+To: Mickaël Salaün <mic@linux.microsoft.com>
 ---
- include/linux/lsm_hooks.h         |  1 +
- security/apparmor/include/net.h   |  6 ++-
- security/apparmor/lsm.c           | 38 ++++-----------
- security/security.c               | 36 +++++++++++++-
- security/selinux/hooks.c          | 78 +++++++++++++++----------------
- security/selinux/include/objsec.h |  5 ++
- security/selinux/netlabel.c       | 23 ++++-----
- security/smack/smack.h            |  5 ++
- security/smack/smack_lsm.c        | 64 ++++++++++++-------------
- security/smack/smack_netfilter.c  |  8 ++--
- 10 files changed, 144 insertions(+), 120 deletions(-)
+ include/linux/audit.h               |  4 +-
+ include/linux/lsm_hooks.h           | 12 ++++-
+ include/linux/security.h            | 67 ++++++++++++++++++++++++--
+ kernel/auditfilter.c                | 24 +++++-----
+ kernel/auditsc.c                    | 13 +++--
+ security/apparmor/lsm.c             |  7 ++-
+ security/bpf/hooks.c                | 12 ++++-
+ security/commoncap.c                |  7 ++-
+ security/integrity/ima/ima_policy.c | 40 +++++++++++-----
+ security/landlock/cred.c            |  2 +-
+ security/landlock/fs.c              |  2 +-
+ security/landlock/ptrace.c          |  2 +-
+ security/landlock/setup.c           |  5 ++
+ security/landlock/setup.h           |  1 +
+ security/loadpin/loadpin.c          |  8 +++-
+ security/lockdown/lockdown.c        |  7 ++-
+ security/safesetid/lsm.c            |  8 +++-
+ security/security.c                 | 74 ++++++++++++++++++++++++-----
+ security/selinux/hooks.c            |  8 +++-
+ security/smack/smack_lsm.c          |  7 ++-
+ security/tomoyo/tomoyo.c            |  8 +++-
+ security/yama/yama_lsm.c            |  7 ++-
+ 22 files changed, 265 insertions(+), 60 deletions(-)
 
+diff --git a/include/linux/audit.h b/include/linux/audit.h
+index 82b7c1116a85..418a485af114 100644
+--- a/include/linux/audit.h
++++ b/include/linux/audit.h
+@@ -11,6 +11,7 @@
+ 
+ #include <linux/sched.h>
+ #include <linux/ptrace.h>
++#include <linux/security.h>
+ #include <uapi/linux/audit.h>
+ #include <uapi/linux/netfilter/nf_tables.h>
+ 
+@@ -65,8 +66,9 @@ struct audit_field {
+ 		kuid_t			uid;
+ 		kgid_t			gid;
+ 		struct {
++			bool		lsm_isset;
+ 			char		*lsm_str;
+-			void		*lsm_rule;
++			void		*lsm_rules[LSMBLOB_ENTRIES];
+ 		};
+ 	};
+ 	u32				op;
 diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
-index cdc5730666d6..1dbed888dab0 100644
+index afd3b16875b0..c61a16f0a5bc 100644
 --- a/include/linux/lsm_hooks.h
 +++ b/include/linux/lsm_hooks.h
-@@ -2055,6 +2055,7 @@ struct lsm_blob_sizes {
- 	int	lbs_cred;
- 	int	lbs_file;
- 	int	lbs_inode;
-+	int	lbs_sock;
- 	int	lbs_superblock;
- 	int	lbs_ipc;
- 	int	lbs_msg_msg;
-diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
-index 7334ac966d01..adac04e3b3cc 100644
---- a/security/apparmor/include/net.h
-+++ b/security/apparmor/include/net.h
-@@ -55,7 +55,11 @@ struct aa_sk_ctx {
- 	struct aa_label *peer;
- };
- 
--#define SK_CTX(X) ((X)->sk_security)
-+static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
+@@ -1570,6 +1570,14 @@ struct security_hook_heads {
+ 	#undef LSM_HOOK
+ } __randomize_layout;
+ 
++/*
++ * Information that identifies a security module.
++ */
++struct lsm_id {
++	const char	*lsm;	/* Name of the LSM */
++	int		slot;	/* Slot in lsmblob if one is allocated */
++};
++
+ /*
+  * Security module hook list structure.
+  * For use with generic list macros for common operations.
+@@ -1578,7 +1586,7 @@ struct security_hook_list {
+ 	struct hlist_node		list;
+ 	struct hlist_head		*head;
+ 	union security_list_options	hook;
+-	char				*lsm;
++	struct lsm_id			*lsmid;
+ } __randomize_layout;
+ 
+ /*
+@@ -1614,7 +1622,7 @@ extern struct security_hook_heads security_hook_heads;
+ extern char *lsm_names;
+ 
+ extern void security_add_hooks(struct security_hook_list *hooks, int count,
+-				char *lsm);
++			       struct lsm_id *lsmid);
+ 
+ #define LSM_FLAG_LEGACY_MAJOR	BIT(0)
+ #define LSM_FLAG_EXCLUSIVE	BIT(1)
+diff --git a/include/linux/security.h b/include/linux/security.h
+index 24eda04221e9..7655bfce4b96 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -133,6 +133,65 @@ enum lockdown_reason {
+ 
+ extern const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1];
+ 
++/*
++ * Data exported by the security modules
++ *
++ * Any LSM that provides secid or secctx based hooks must be included.
++ */
++#define LSMBLOB_ENTRIES ( \
++	(IS_ENABLED(CONFIG_SECURITY_SELINUX) ? 1 : 0) + \
++	(IS_ENABLED(CONFIG_SECURITY_SMACK) ? 1 : 0) + \
++	(IS_ENABLED(CONFIG_SECURITY_APPARMOR) ? 1 : 0) + \
++	(IS_ENABLED(CONFIG_BPF_LSM) ? 1 : 0))
++
++struct lsmblob {
++	u32     secid[LSMBLOB_ENTRIES];
++};
++
++#define LSMBLOB_INVALID		-1	/* Not a valid LSM slot number */
++#define LSMBLOB_NEEDED		-2	/* Slot requested on initialization */
++#define LSMBLOB_NOT_NEEDED	-3	/* Slot not requested */
++
++/**
++ * lsmblob_init - initialize an lsmblob structure
++ * @blob: Pointer to the data to initialize
++ * @secid: The initial secid value
++ *
++ * Set all secid for all modules to the specified value.
++ */
++static inline void lsmblob_init(struct lsmblob *blob, u32 secid)
 +{
-+	return sk->sk_security + apparmor_blob_sizes.lbs_sock;
++	int i;
++
++	for (i = 0; i < LSMBLOB_ENTRIES; i++)
++		blob->secid[i] = secid;
 +}
 +
- #define SOCK_ctx(X) SOCK_INODE(X)->i_security
- #define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P)				  \
- 	struct lsm_network_audit NAME ## _net = { .sk = (SK),		  \
++/**
++ * lsmblob_is_set - report if there is an value in the lsmblob
++ * @blob: Pointer to the exported LSM data
++ *
++ * Returns true if there is a secid set, false otherwise
++ */
++static inline bool lsmblob_is_set(struct lsmblob *blob)
++{
++	struct lsmblob empty = {};
++
++	return !!memcmp(blob, &empty, sizeof(*blob));
++}
++
++/**
++ * lsmblob_equal - report if the two lsmblob's are equal
++ * @bloba: Pointer to one LSM data
++ * @blobb: Pointer to the other LSM data
++ *
++ * Returns true if all entries in the two are equal, false otherwise
++ */
++static inline bool lsmblob_equal(struct lsmblob *bloba, struct lsmblob *blobb)
++{
++	return !memcmp(bloba, blobb, sizeof(*bloba));
++}
++
+ /* These functions are in security/commoncap.c */
+ extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
+ 		       int cap, unsigned int opts);
+@@ -1881,8 +1940,8 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer)
+ #ifdef CONFIG_SECURITY
+ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
+ int security_audit_rule_known(struct audit_krule *krule);
+-int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule);
+-void security_audit_rule_free(void *lsmrule);
++int security_audit_rule_match(u32 secid, u32 field, u32 op, void **lsmrule);
++void security_audit_rule_free(void **lsmrule);
+ 
+ #else
+ 
+@@ -1898,12 +1957,12 @@ static inline int security_audit_rule_known(struct audit_krule *krule)
+ }
+ 
+ static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
+-					    void *lsmrule)
++					    void **lsmrule)
+ {
+ 	return 0;
+ }
+ 
+-static inline void security_audit_rule_free(void *lsmrule)
++static inline void security_audit_rule_free(void **lsmrule)
+ { }
+ 
+ #endif /* CONFIG_SECURITY */
+diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
+index db2c6b59dfc3..a2340e81cfa7 100644
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -74,7 +74,7 @@ static void audit_free_lsm_field(struct audit_field *f)
+ 	case AUDIT_OBJ_LEV_LOW:
+ 	case AUDIT_OBJ_LEV_HIGH:
+ 		kfree(f->lsm_str);
+-		security_audit_rule_free(f->lsm_rule);
++		security_audit_rule_free(f->lsm_rules);
+ 	}
+ }
+ 
+@@ -519,9 +519,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
+ 				goto exit_free;
+ 			}
+ 			entry->rule.buflen += f_val;
++			f->lsm_isset = true;
+ 			f->lsm_str = str;
+ 			err = security_audit_rule_init(f->type, f->op, str,
+-						       (void **)&f->lsm_rule);
++						       f->lsm_rules);
+ 			/* Keep currently invalid fields around in case they
+ 			 * become valid after a policy reload. */
+ 			if (err == -EINVAL) {
+@@ -774,7 +775,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
+ 	return 0;
+ }
+ 
+-/* Duplicate LSM field information.  The lsm_rule is opaque, so must be
++/* Duplicate LSM field information.  The lsm_rules is opaque, so must be
+  * re-initialized. */
+ static inline int audit_dupe_lsm_field(struct audit_field *df,
+ 					   struct audit_field *sf)
+@@ -788,9 +789,9 @@ static inline int audit_dupe_lsm_field(struct audit_field *df,
+ 		return -ENOMEM;
+ 	df->lsm_str = lsm_str;
+ 
+-	/* our own (refreshed) copy of lsm_rule */
++	/* our own (refreshed) copy of lsm_rules */
+ 	ret = security_audit_rule_init(df->type, df->op, df->lsm_str,
+-				       (void **)&df->lsm_rule);
++				       df->lsm_rules);
+ 	/* Keep currently invalid fields around in case they
+ 	 * become valid after a policy reload. */
+ 	if (ret == -EINVAL) {
+@@ -842,7 +843,7 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old)
+ 	new->tree = old->tree;
+ 	memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
+ 
+-	/* deep copy this information, updating the lsm_rule fields, because
++	/* deep copy this information, updating the lsm_rules fields, because
+ 	 * the originals will all be freed when the old rule is freed. */
+ 	for (i = 0; i < fcount; i++) {
+ 		switch (new->fields[i].type) {
+@@ -1358,11 +1359,12 @@ int audit_filter(int msgtype, unsigned int listtype)
+ 			case AUDIT_SUBJ_TYPE:
+ 			case AUDIT_SUBJ_SEN:
+ 			case AUDIT_SUBJ_CLR:
+-				if (f->lsm_rule) {
++				if (f->lsm_isset) {
+ 					security_task_getsecid_subj(current,
+ 								    &sid);
+ 					result = security_audit_rule_match(sid,
+-						   f->type, f->op, f->lsm_rule);
++						   f->type, f->op,
++						   f->lsm_rules);
+ 				}
+ 				break;
+ 			case AUDIT_EXE:
+@@ -1389,7 +1391,7 @@ int audit_filter(int msgtype, unsigned int listtype)
+ 	return ret;
+ }
+ 
+-static int update_lsm_rule(struct audit_krule *r)
++static int update_lsm_rules(struct audit_krule *r)
+ {
+ 	struct audit_entry *entry = container_of(r, struct audit_entry, rule);
+ 	struct audit_entry *nentry;
+@@ -1421,7 +1423,7 @@ static int update_lsm_rule(struct audit_krule *r)
+ 	return err;
+ }
+ 
+-/* This function will re-initialize the lsm_rule field of all applicable rules.
++/* This function will re-initialize the lsm_rules field of all applicable rules.
+  * It will traverse the filter lists serarching for rules that contain LSM
+  * specific filter fields.  When such a rule is found, it is copied, the
+  * LSM field is re-initialized, and the old rule is replaced with the
+@@ -1436,7 +1438,7 @@ int audit_update_lsm_rules(void)
+ 
+ 	for (i = 0; i < AUDIT_NR_FILTERS; i++) {
+ 		list_for_each_entry_safe(r, n, &audit_rules_list[i], list) {
+-			int res = update_lsm_rule(r);
++			int res = update_lsm_rules(r);
+ 			if (!err)
+ 				err = res;
+ 		}
+diff --git a/kernel/auditsc.c b/kernel/auditsc.c
+index 8dd73a64f921..acbd896f54a5 100644
+--- a/kernel/auditsc.c
++++ b/kernel/auditsc.c
+@@ -671,14 +671,13 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 			   match for now to avoid losing information that
+ 			   may be wanted.   An error message will also be
+ 			   logged upon error */
+-			if (f->lsm_rule) {
++			if (f->lsm_isset) {
+ 				if (need_sid) {
+ 					security_task_getsecid_subj(tsk, &sid);
+ 					need_sid = 0;
+ 				}
+ 				result = security_audit_rule_match(sid, f->type,
+-								   f->op,
+-								   f->lsm_rule);
++							f->op, f->lsm_rules);
+ 			}
+ 			break;
+ 		case AUDIT_OBJ_USER:
+@@ -688,21 +687,21 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 		case AUDIT_OBJ_LEV_HIGH:
+ 			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
+ 			   also applies here */
+-			if (f->lsm_rule) {
++			if (f->lsm_isset) {
+ 				/* Find files that match */
+ 				if (name) {
+ 					result = security_audit_rule_match(
+ 								name->osid,
+ 								f->type,
+ 								f->op,
+-								f->lsm_rule);
++								f->lsm_rules);
+ 				} else if (ctx) {
+ 					list_for_each_entry(n, &ctx->names_list, list) {
+ 						if (security_audit_rule_match(
+ 								n->osid,
+ 								f->type,
+ 								f->op,
+-								f->lsm_rule)) {
++								f->lsm_rules)) {
+ 							++result;
+ 							break;
+ 						}
+@@ -713,7 +712,7 @@ static int audit_filter_rules(struct task_struct *tsk,
+ 					break;
+ 				if (security_audit_rule_match(ctx->ipc.osid,
+ 							      f->type, f->op,
+-							      f->lsm_rule))
++							      f->lsm_rules))
+ 					++result;
+ 			}
+ 			break;
 diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
-index 49d664ddff44..2716e7731279 100644
+index 4113516fb62e..392e25940d1f 100644
 --- a/security/apparmor/lsm.c
 +++ b/security/apparmor/lsm.c
-@@ -757,33 +757,15 @@ static int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo
- 	return error;
- }
- 
--/**
-- * apparmor_sk_alloc_security - allocate and attach the sk_security field
-- */
--static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
--{
--	struct aa_sk_ctx *ctx;
--
--	ctx = kzalloc(sizeof(*ctx), flags);
--	if (!ctx)
--		return -ENOMEM;
--
--	SK_CTX(sk) = ctx;
--
--	return 0;
--}
--
- /**
-  * apparmor_sk_free_security - free the sk_security field
-  */
- static void apparmor_sk_free_security(struct sock *sk)
- {
--	struct aa_sk_ctx *ctx = SK_CTX(sk);
-+	struct aa_sk_ctx *ctx = aa_sock(sk);
- 
--	SK_CTX(sk) = NULL;
- 	aa_put_label(ctx->label);
- 	aa_put_label(ctx->peer);
--	kfree(ctx);
- }
- 
- /**
-@@ -792,8 +774,8 @@ static void apparmor_sk_free_security(struct sock *sk)
- static void apparmor_sk_clone_security(const struct sock *sk,
- 				       struct sock *newsk)
- {
--	struct aa_sk_ctx *ctx = SK_CTX(sk);
--	struct aa_sk_ctx *new = SK_CTX(newsk);
-+	struct aa_sk_ctx *ctx = aa_sock(sk);
-+	struct aa_sk_ctx *new = aa_sock(newsk);
- 
- 	new->label = aa_get_label(ctx->label);
- 	new->peer = aa_get_label(ctx->peer);
-@@ -844,7 +826,7 @@ static int apparmor_socket_post_create(struct socket *sock, int family,
- 		label = aa_get_current_label();
- 
- 	if (sock->sk) {
--		struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
-+		struct aa_sk_ctx *ctx = aa_sock(sock->sk);
- 
- 		aa_put_label(ctx->label);
- 		ctx->label = aa_get_label(label);
-@@ -1029,7 +1011,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how)
-  */
- static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
- {
--	struct aa_sk_ctx *ctx = SK_CTX(sk);
-+	struct aa_sk_ctx *ctx = aa_sock(sk);
- 
- 	if (!skb->secmark)
- 		return 0;
-@@ -1042,7 +1024,7 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
- 
- static struct aa_label *sk_peer_label(struct sock *sk)
- {
--	struct aa_sk_ctx *ctx = SK_CTX(sk);
-+	struct aa_sk_ctx *ctx = aa_sock(sk);
- 
- 	if (ctx->peer)
- 		return ctx->peer;
-@@ -1126,7 +1108,7 @@ static int apparmor_socket_getpeersec_dgram(struct socket *sock,
-  */
- static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
- {
--	struct aa_sk_ctx *ctx = SK_CTX(sk);
-+	struct aa_sk_ctx *ctx = aa_sock(sk);
- 
- 	if (!ctx->label)
- 		ctx->label = aa_get_current_label();
-@@ -1136,7 +1118,7 @@ static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
- static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
- 				      struct request_sock *req)
- {
--	struct aa_sk_ctx *ctx = SK_CTX(sk);
-+	struct aa_sk_ctx *ctx = aa_sock(sk);
- 
- 	if (!skb->secmark)
- 		return 0;
-@@ -1153,6 +1135,7 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
- 	.lbs_cred = sizeof(struct aa_task_ctx *),
- 	.lbs_file = sizeof(struct aa_file_ctx),
- 	.lbs_task = sizeof(struct aa_task_ctx),
-+	.lbs_sock = sizeof(struct aa_sk_ctx),
+@@ -1161,6 +1161,11 @@ struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
+ 	.lbs_sock = sizeof(struct aa_sk_ctx),
  };
  
++static struct lsm_id apparmor_lsmid __lsm_ro_after_init = {
++	.lsm  = "apparmor",
++	.slot = LSMBLOB_NEEDED
++};
++
  static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
-@@ -1189,7 +1172,6 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
- 	LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
- 	LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
- 
--	LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
- 	LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
- 	LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
- 
-@@ -1581,7 +1563,7 @@ static unsigned int apparmor_ip_postroute(void *priv,
- 	if (sk == NULL)
- 		return NF_ACCEPT;
- 
--	ctx = SK_CTX(sk);
-+	ctx = aa_sock(sk);
- 	if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND,
- 				    skb->secmark, sk))
- 		return NF_ACCEPT;
+ 	LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
+ 	LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
+@@ -1862,7 +1867,7 @@ static int __init apparmor_init(void)
+ 		goto buffers_out;
+ 	}
+ 	security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks),
+-				"apparmor");
++				&apparmor_lsmid);
+ 
+ 	/* Report that AppArmor successfully initialized */
+ 	apparmor_initialized = 1;
+diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c
+index e5971fa74fd7..7a58fe9ab8c4 100644
+--- a/security/bpf/hooks.c
++++ b/security/bpf/hooks.c
+@@ -15,9 +15,19 @@ static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {
+ 	LSM_HOOK_INIT(task_free, bpf_task_storage_free),
+ };
+ 
++/*
++ * slot has to be LSMBLOB_NEEDED because some of the hooks
++ * supplied by this module require a slot.
++ */
++struct lsm_id bpf_lsmid __lsm_ro_after_init = {
++	.lsm = "bpf",
++	.slot = LSMBLOB_NEEDED
++};
++
+ static int __init bpf_lsm_init(void)
+ {
+-	security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), "bpf");
++	security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks),
++			   &bpf_lsmid);
+ 	pr_info("LSM support for eBPF active\n");
+ 	return 0;
+ }
+diff --git a/security/commoncap.c b/security/commoncap.c
+index 3f810d37b71b..628685cf20e3 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -1443,6 +1443,11 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
+ 
+ #ifdef CONFIG_SECURITY
+ 
++static struct lsm_id capability_lsmid __lsm_ro_after_init = {
++	.lsm  = "capability",
++	.slot = LSMBLOB_NOT_NEEDED
++};
++
+ static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
+ 	LSM_HOOK_INIT(capable, cap_capable),
+ 	LSM_HOOK_INIT(settime, cap_settime),
+@@ -1467,7 +1472,7 @@ static struct security_hook_list capability_hooks[] __lsm_ro_after_init = {
+ static int __init capability_init(void)
+ {
+ 	security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks),
+-				"capability");
++			   &capability_lsmid);
+ 	return 0;
+ }
+ 
+diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
+index fd5d46e511f1..5c40677e881c 100644
+--- a/security/integrity/ima/ima_policy.c
++++ b/security/integrity/ima/ima_policy.c
+@@ -80,7 +80,7 @@ struct ima_rule_entry {
+ 	bool (*fowner_op)(kuid_t, kuid_t); /* uid_eq(), uid_gt(), uid_lt() */
+ 	int pcr;
+ 	struct {
+-		void *rule;	/* LSM file metadata specific */
++		void *rules[LSMBLOB_ENTRIES]; /* LSM file metadata specific */
+ 		char *args_p;	/* audit value */
+ 		int type;	/* audit type */
+ 	} lsm[MAX_LSM_RULES];
+@@ -90,6 +90,22 @@ struct ima_rule_entry {
+ 	struct ima_template_desc *template;
+ };
+ 
++/**
++ * ima_lsm_isset - Is a rule set for any of the active security modules
++ * @rules: The set of IMA rules to check
++ *
++ * If a rule is set for any LSM return true, otherwise return false.
++ */
++static inline bool ima_lsm_isset(void *rules[])
++{
++	int i;
++
++	for (i = 0; i < LSMBLOB_ENTRIES; i++)
++		if (rules[i])
++			return true;
++	return false;
++}
++
+ /*
+  * Without LSM specific knowledge, the default policy can only be
+  * written in terms of .action, .func, .mask, .fsmagic, .uid, and .fowner
+@@ -335,9 +351,11 @@ static void ima_free_rule_opt_list(struct ima_rule_opt_list *opt_list)
+ static void ima_lsm_free_rule(struct ima_rule_entry *entry)
+ {
+ 	int i;
++	int r;
+ 
+ 	for (i = 0; i < MAX_LSM_RULES; i++) {
+-		ima_filter_rule_free(entry->lsm[i].rule);
++		for (r = 0; r < LSMBLOB_ENTRIES; r++)
++			ima_filter_rule_free(entry->lsm[i].rules[r]);
+ 		kfree(entry->lsm[i].args_p);
+ 	}
+ }
+@@ -388,8 +406,8 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
+ 
+ 		ima_filter_rule_init(nentry->lsm[i].type, Audit_equal,
+ 				     nentry->lsm[i].args_p,
+-				     &nentry->lsm[i].rule);
+-		if (!nentry->lsm[i].rule)
++				     &nentry->lsm[i].rules[0]);
++		if (!ima_lsm_isset(nentry->lsm[i].rules))
+ 			pr_warn("rule for LSM \'%s\' is undefined\n",
+ 				nentry->lsm[i].args_p);
+ 	}
+@@ -578,7 +596,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
+ 		int rc = 0;
+ 		u32 osid;
+ 
+-		if (!rule->lsm[i].rule) {
++		if (!ima_lsm_isset(rule->lsm[i].rules)) {
+ 			if (!rule->lsm[i].args_p)
+ 				continue;
+ 			else
+@@ -591,14 +609,14 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
+ 			security_inode_getsecid(inode, &osid);
+ 			rc = ima_filter_rule_match(osid, rule->lsm[i].type,
+ 						   Audit_equal,
+-						   rule->lsm[i].rule);
++						   rule->lsm[i].rules);
+ 			break;
+ 		case LSM_SUBJ_USER:
+ 		case LSM_SUBJ_ROLE:
+ 		case LSM_SUBJ_TYPE:
+ 			rc = ima_filter_rule_match(secid, rule->lsm[i].type,
+ 						   Audit_equal,
+-						   rule->lsm[i].rule);
++						   rule->lsm[i].rules);
+ 			break;
+ 		default:
+ 			break;
+@@ -994,7 +1012,7 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
+ {
+ 	int result;
+ 
+-	if (entry->lsm[lsm_rule].rule)
++	if (ima_lsm_isset(entry->lsm[lsm_rule].rules))
+ 		return -EINVAL;
+ 
+ 	entry->lsm[lsm_rule].args_p = match_strdup(args);
+@@ -1004,8 +1022,8 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
+ 	entry->lsm[lsm_rule].type = audit_type;
+ 	result = ima_filter_rule_init(entry->lsm[lsm_rule].type, Audit_equal,
+ 				      entry->lsm[lsm_rule].args_p,
+-				      &entry->lsm[lsm_rule].rule);
+-	if (!entry->lsm[lsm_rule].rule) {
++				      &entry->lsm[lsm_rule].rules[0]);
++	if (!ima_lsm_isset(entry->lsm[lsm_rule].rules)) {
+ 		pr_warn("rule for LSM \'%s\' is undefined\n",
+ 			entry->lsm[lsm_rule].args_p);
+ 
+@@ -1812,7 +1830,7 @@ int ima_policy_show(struct seq_file *m, void *v)
+ 	}
+ 
+ 	for (i = 0; i < MAX_LSM_RULES; i++) {
+-		if (entry->lsm[i].rule) {
++		if (ima_lsm_isset(entry->lsm[i].rules)) {
+ 			switch (i) {
+ 			case LSM_OBJ_USER:
+ 				seq_printf(m, pt(Opt_obj_user),
+diff --git a/security/landlock/cred.c b/security/landlock/cred.c
+index 6725af24c684..56b121d65436 100644
+--- a/security/landlock/cred.c
++++ b/security/landlock/cred.c
+@@ -42,5 +42,5 @@ static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
+ __init void landlock_add_cred_hooks(void)
+ {
+ 	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
+-			LANDLOCK_NAME);
++			&landlock_lsmid);
+ }
+diff --git a/security/landlock/fs.c b/security/landlock/fs.c
+index 97b8e421f617..319e90e9290c 100644
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -688,5 +688,5 @@ static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
+ __init void landlock_add_fs_hooks(void)
+ {
+ 	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
+-			LANDLOCK_NAME);
++			&landlock_lsmid);
+ }
+diff --git a/security/landlock/ptrace.c b/security/landlock/ptrace.c
+index f55b82446de2..54ccf55a077a 100644
+--- a/security/landlock/ptrace.c
++++ b/security/landlock/ptrace.c
+@@ -116,5 +116,5 @@ static struct security_hook_list landlock_hooks[] __lsm_ro_after_init = {
+ __init void landlock_add_ptrace_hooks(void)
+ {
+ 	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
+-			LANDLOCK_NAME);
++			&landlock_lsmid);
+ }
+diff --git a/security/landlock/setup.c b/security/landlock/setup.c
+index f8e8e980454c..759e00b9436c 100644
+--- a/security/landlock/setup.c
++++ b/security/landlock/setup.c
+@@ -23,6 +23,11 @@ struct lsm_blob_sizes landlock_blob_sizes __lsm_ro_after_init = {
+ 	.lbs_superblock = sizeof(struct landlock_superblock_security),
+ };
+ 
++struct lsm_id landlock_lsmid __lsm_ro_after_init = {
++	.lsm = LANDLOCK_NAME,
++	.slot = LSMBLOB_NOT_NEEDED,
++};
++
+ static int __init landlock_init(void)
+ {
+ 	landlock_add_cred_hooks();
+diff --git a/security/landlock/setup.h b/security/landlock/setup.h
+index 1daffab1ab4b..38bce5b172dc 100644
+--- a/security/landlock/setup.h
++++ b/security/landlock/setup.h
+@@ -14,5 +14,6 @@
+ extern bool landlock_initialized;
+ 
+ extern struct lsm_blob_sizes landlock_blob_sizes;
++extern struct lsm_id landlock_lsmid;
+ 
+ #endif /* _SECURITY_LANDLOCK_SETUP_H */
+diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
+index b12f7d986b1e..b569f3bc170b 100644
+--- a/security/loadpin/loadpin.c
++++ b/security/loadpin/loadpin.c
+@@ -192,6 +192,11 @@ static int loadpin_load_data(enum kernel_load_data_id id, bool contents)
+ 	return loadpin_read_file(NULL, (enum kernel_read_file_id) id, contents);
+ }
+ 
++static struct lsm_id loadpin_lsmid __lsm_ro_after_init = {
++	.lsm  = "loadpin",
++	.slot = LSMBLOB_NOT_NEEDED
++};
++
+ static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
+ 	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
+ 	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
+@@ -239,7 +244,8 @@ static int __init loadpin_init(void)
+ 	pr_info("ready to pin (currently %senforcing)\n",
+ 		enforce ? "" : "not ");
+ 	parse_exclude();
+-	security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks), "loadpin");
++	security_add_hooks(loadpin_hooks, ARRAY_SIZE(loadpin_hooks),
++			   &loadpin_lsmid);
+ 	return 0;
+ }
+ 
+diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
+index 87cbdc64d272..4e24ea3f7b7e 100644
+--- a/security/lockdown/lockdown.c
++++ b/security/lockdown/lockdown.c
+@@ -75,6 +75,11 @@ static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
+ 	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
+ };
+ 
++static struct lsm_id lockdown_lsmid __lsm_ro_after_init = {
++	.lsm = "lockdown",
++	.slot = LSMBLOB_NOT_NEEDED
++};
++
+ static int __init lockdown_lsm_init(void)
+ {
+ #if defined(CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY)
+@@ -83,7 +88,7 @@ static int __init lockdown_lsm_init(void)
+ 	lock_kernel_down("Kernel configuration", LOCKDOWN_CONFIDENTIALITY_MAX);
+ #endif
+ 	security_add_hooks(lockdown_hooks, ARRAY_SIZE(lockdown_hooks),
+-			   "lockdown");
++			   &lockdown_lsmid);
+ 	return 0;
+ }
+ 
+diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c
+index 963f4ad9cb66..0c368950dc14 100644
+--- a/security/safesetid/lsm.c
++++ b/security/safesetid/lsm.c
+@@ -241,6 +241,11 @@ static int safesetid_task_fix_setgid(struct cred *new,
+ 	return -EACCES;
+ }
+ 
++static struct lsm_id safesetid_lsmid __lsm_ro_after_init = {
++	.lsm  = "safesetid",
++	.slot = LSMBLOB_NOT_NEEDED
++};
++
+ static struct security_hook_list safesetid_security_hooks[] = {
+ 	LSM_HOOK_INIT(task_fix_setuid, safesetid_task_fix_setuid),
+ 	LSM_HOOK_INIT(task_fix_setgid, safesetid_task_fix_setgid),
+@@ -250,7 +255,8 @@ static struct security_hook_list safesetid_security_hooks[] = {
+ static int __init safesetid_security_init(void)
+ {
+ 	security_add_hooks(safesetid_security_hooks,
+-			   ARRAY_SIZE(safesetid_security_hooks), "safesetid");
++			   ARRAY_SIZE(safesetid_security_hooks),
++			   &safesetid_lsmid);
+ 
+ 	/* Report that SafeSetID successfully initialized */
+ 	safesetid_initialized = 1;
 diff --git a/security/security.c b/security/security.c
-index 550988a0f024..e32b7180282e 100644
+index 335c313a668d..5f1b281511f2 100644
 --- a/security/security.c
 +++ b/security/security.c
-@@ -32,6 +32,7 @@
- #include <linux/string.h>
- #include <linux/msg.h>
- #include <net/flow.h>
-+#include <net/sock.h>
- 
- #define MAX_LSM_EVM_XATTR	2
- 
-@@ -172,6 +173,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
- 	lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
- 	lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
- 	lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
-+	lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
- 	lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
- 	lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
- }
-@@ -306,6 +308,7 @@ static void __init ordered_lsm_init(void)
- 	init_debug("inode blob size      = %d\n", blob_sizes.lbs_inode);
- 	init_debug("ipc blob size        = %d\n", blob_sizes.lbs_ipc);
- 	init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
-+	init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
+@@ -344,6 +344,7 @@ static void __init ordered_lsm_init(void)
+ 	init_debug("sock blob size       = %d\n", blob_sizes.lbs_sock);
  	init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
  	init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
- 
-@@ -605,6 +608,28 @@ static void __init lsm_early_task(struct task_struct *task)
- 		panic("%s: Early task alloc failed.\n", __func__);
- }
- 
-+/**
-+ * lsm_sock_alloc - allocate a composite sock blob
-+ * @sock: the sock that needs a blob
-+ * @priority: allocation mode
-+ *
-+ * Allocate the sock blob for all the modules
-+ *
-+ * Returns 0, or -ENOMEM if memory can't be allocated.
++	init_debug("lsmblob size         = %zu\n", sizeof(struct lsmblob));
+ 
+ 	/*
+ 	 * Create any kmem_caches needed for blobs
+@@ -471,21 +472,38 @@ static int lsm_append(const char *new, char **result)
+ 	return 0;
+ }
+ 
++/*
++ * Current index to use while initializing the lsmblob secid list.
 + */
-+int lsm_sock_alloc(struct sock *sock, gfp_t priority)
-+{
-+	if (blob_sizes.lbs_sock == 0) {
-+		sock->sk_security = NULL;
++static int lsm_slot __lsm_ro_after_init;
++
+ /**
+  * security_add_hooks - Add a modules hooks to the hook lists.
+  * @hooks: the hooks to add
+  * @count: the number of hooks to add
+- * @lsm: the name of the security module
++ * @lsmid: the identification information for the security module
+  *
+  * Each LSM has to register its hooks with the infrastructure.
++ * If the LSM is using hooks that export secids allocate a slot
++ * for it in the lsmblob.
+  */
+ void __init security_add_hooks(struct security_hook_list *hooks, int count,
+-				char *lsm)
++			       struct lsm_id *lsmid)
+ {
+ 	int i;
+ 
++	WARN_ON(!lsmid->slot || !lsmid->lsm);
++
++	if (lsmid->slot == LSMBLOB_NEEDED) {
++		if (lsm_slot >= LSMBLOB_ENTRIES)
++			panic("%s Too many LSMs registered.\n", __func__);
++		lsmid->slot = lsm_slot++;
++		init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm,
++			   lsmid->slot);
++	}
++
+ 	for (i = 0; i < count; i++) {
+-		hooks[i].lsm = lsm;
++		hooks[i].lsmid = lsmid;
+ 		hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
+ 	}
+ 
+@@ -494,7 +512,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
+ 	 * and fix this up afterwards.
+ 	 */
+ 	if (slab_is_available()) {
+-		if (lsm_append(lsm, &lsm_names) < 0)
++		if (lsm_append(lsmid->lsm, &lsm_names) < 0)
+ 			panic("%s - Cannot get early memory.\n", __func__);
+ 	}
+ }
+@@ -2070,7 +2088,7 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
+ 	struct security_hook_list *hp;
+ 
+ 	hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
+-		if (lsm != NULL && strcmp(lsm, hp->lsm))
++		if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
+ 			continue;
+ 		return hp->hook.getprocattr(p, name, value);
+ 	}
+@@ -2083,7 +2101,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
+ 	struct security_hook_list *hp;
+ 
+ 	hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
+-		if (lsm != NULL && strcmp(lsm, hp->lsm))
++		if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm))
+ 			continue;
+ 		return hp->hook.setprocattr(name, value, size);
+ 	}
+@@ -2576,7 +2594,24 @@ int security_key_getsecurity(struct key *key, char **_buffer)
+ 
+ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
+ {
+-	return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule);
++	struct security_hook_list *hp;
++	bool one_is_good = false;
++	int rc = 0;
++	int trc;
++
++	hlist_for_each_entry(hp, &security_hook_heads.audit_rule_init, list) {
++		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
++			continue;
++		trc = hp->hook.audit_rule_init(field, op, rulestr,
++					       &lsmrule[hp->lsmid->slot]);
++		if (trc == 0)
++			one_is_good = true;
++		else
++			rc = trc;
++	}
++	if (one_is_good)
 +		return 0;
++	return rc;
+ }
+ 
+ int security_audit_rule_known(struct audit_krule *krule)
+@@ -2584,14 +2619,31 @@ int security_audit_rule_known(struct audit_krule *krule)
+ 	return call_int_hook(audit_rule_known, 0, krule);
+ }
+ 
+-void security_audit_rule_free(void *lsmrule)
++void security_audit_rule_free(void **lsmrule)
+ {
+-	call_void_hook(audit_rule_free, lsmrule);
++	struct security_hook_list *hp;
++
++	hlist_for_each_entry(hp, &security_hook_heads.audit_rule_free, list) {
++		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
++			continue;
++		hp->hook.audit_rule_free(lsmrule[hp->lsmid->slot]);
 +	}
-+
-+	sock->sk_security = kzalloc(blob_sizes.lbs_sock, priority);
-+	if (sock->sk_security == NULL)
-+		return -ENOMEM;
+ }
+ 
+-int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
++int security_audit_rule_match(u32 secid, u32 field, u32 op, void **lsmrule)
+ {
+-	return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule);
++	struct security_hook_list *hp;
++	int rc;
++
++	hlist_for_each_entry(hp, &security_hook_heads.audit_rule_match, list) {
++		if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
++			continue;
++		rc = hp->hook.audit_rule_match(secid, field, op,
++					       &lsmrule[hp->lsmid->slot]);
++		if (rc)
++			return rc;
++	}
 +	return 0;
-+}
-+
- /**
-  * lsm_superblock_alloc - allocate a composite superblock blob
-  * @sb: the superblock that needs a blob
-@@ -2048,12 +2073,21 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram);
- 
- int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
- {
--	return call_int_hook(sk_alloc_security, 0, sk, family, priority);
-+	int rc = lsm_sock_alloc(sk, priority);
-+
-+	if (unlikely(rc))
-+		return rc;
-+	rc = call_int_hook(sk_alloc_security, 0, sk, family, priority);
-+	if (unlikely(rc))
-+		security_sk_free(sk);
-+	return rc;
- }
- 
- void security_sk_free(struct sock *sk)
- {
- 	call_void_hook(sk_free_security, sk);
-+	kfree(sk->sk_security);
-+	sk->sk_security = NULL;
- }
- 
- void security_sk_clone(const struct sock *sk, struct sock *newsk)
+ }
+ #endif /* CONFIG_AUDIT */
+ 
 diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index 7478d8eda00a..f38a6f484613 100644
+index e2c4a1fd952f..f84b6c274a10 100644
 --- a/security/selinux/hooks.c
 +++ b/security/selinux/hooks.c
-@@ -4319,7 +4319,7 @@ static int socket_sockcreate_sid(const struct task_security_struct *tsec,
- 
- static int sock_has_perm(struct sock *sk, u32 perms)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	struct common_audit_data ad;
- 	struct lsm_network_audit net = {0,};
- 
-@@ -4376,7 +4376,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
- 	isec->initialized = LABEL_INITIALIZED;
- 
- 	if (sock->sk) {
--		sksec = sock->sk->sk_security;
-+		sksec = selinux_sock(sock->sk);
- 		sksec->sclass = sclass;
- 		sksec->sid = sid;
- 		/* Allows detection of the first association on this socket */
-@@ -4392,8 +4392,8 @@ static int selinux_socket_post_create(struct socket *sock, int family,
- static int selinux_socket_socketpair(struct socket *socka,
- 				     struct socket *sockb)
- {
--	struct sk_security_struct *sksec_a = socka->sk->sk_security;
--	struct sk_security_struct *sksec_b = sockb->sk->sk_security;
-+	struct sk_security_struct *sksec_a = selinux_sock(socka->sk);
-+	struct sk_security_struct *sksec_b = selinux_sock(sockb->sk);
- 
- 	sksec_a->peer_sid = sksec_b->sid;
- 	sksec_b->peer_sid = sksec_a->sid;
-@@ -4408,7 +4408,7 @@ static int selinux_socket_socketpair(struct socket *socka,
- static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
- {
- 	struct sock *sk = sock->sk;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	u16 family;
- 	int err;
- 
-@@ -4540,7 +4540,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
- 					 struct sockaddr *address, int addrlen)
- {
- 	struct sock *sk = sock->sk;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	int err;
- 
- 	err = sock_has_perm(sk, SOCKET__CONNECT);
-@@ -4711,9 +4711,9 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
- 					      struct sock *other,
- 					      struct sock *newsk)
- {
--	struct sk_security_struct *sksec_sock = sock->sk_security;
--	struct sk_security_struct *sksec_other = other->sk_security;
--	struct sk_security_struct *sksec_new = newsk->sk_security;
-+	struct sk_security_struct *sksec_sock = selinux_sock(sock);
-+	struct sk_security_struct *sksec_other = selinux_sock(other);
-+	struct sk_security_struct *sksec_new = selinux_sock(newsk);
- 	struct common_audit_data ad;
- 	struct lsm_network_audit net = {0,};
- 	int err;
-@@ -4745,8 +4745,8 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
- static int selinux_socket_unix_may_send(struct socket *sock,
- 					struct socket *other)
- {
--	struct sk_security_struct *ssec = sock->sk->sk_security;
--	struct sk_security_struct *osec = other->sk->sk_security;
-+	struct sk_security_struct *ssec = selinux_sock(sock->sk);
-+	struct sk_security_struct *osec = selinux_sock(other->sk);
- 	struct common_audit_data ad;
- 	struct lsm_network_audit net = {0,};
- 
-@@ -4788,7 +4788,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
- 				       u16 family)
- {
- 	int err = 0;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	u32 sk_sid = sksec->sid;
- 	struct common_audit_data ad;
- 	struct lsm_network_audit net = {0,};
-@@ -4821,7 +4821,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
- static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
- {
- 	int err;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	u16 family = sk->sk_family;
- 	u32 sk_sid = sksec->sid;
- 	struct common_audit_data ad;
-@@ -4889,13 +4889,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
- 	return err;
- }
- 
--static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
--					    int __user *optlen, unsigned len)
-+static int selinux_socket_getpeersec_stream(struct socket *sock,
-+					    __user char *optval,
-+					    __user int *optlen,
-+					    unsigned int len)
- {
- 	int err = 0;
- 	char *scontext;
- 	u32 scontext_len;
--	struct sk_security_struct *sksec = sock->sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sock->sk);
- 	u32 peer_sid = SECSID_NULL;
- 
- 	if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
-@@ -4955,34 +4957,27 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
- 
- static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
- {
--	struct sk_security_struct *sksec;
--
--	sksec = kzalloc(sizeof(*sksec), priority);
--	if (!sksec)
--		return -ENOMEM;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 	sksec->peer_sid = SECINITSID_UNLABELED;
- 	sksec->sid = SECINITSID_UNLABELED;
- 	sksec->sclass = SECCLASS_SOCKET;
- 	selinux_netlbl_sk_security_reset(sksec);
--	sk->sk_security = sksec;
- 
- 	return 0;
- }
- 
- static void selinux_sk_free_security(struct sock *sk)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
--	sk->sk_security = NULL;
- 	selinux_netlbl_sk_security_free(sksec);
--	kfree(sksec);
- }
- 
- static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
--	struct sk_security_struct *newsksec = newsk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
-+	struct sk_security_struct *newsksec = selinux_sock(newsk);
- 
- 	newsksec->sid = sksec->sid;
- 	newsksec->peer_sid = sksec->peer_sid;
-@@ -4996,7 +4991,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
- 	if (!sk)
- 		*secid = SECINITSID_ANY_SOCKET;
- 	else {
--		struct sk_security_struct *sksec = sk->sk_security;
-+		struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 		*secid = sksec->sid;
- 	}
-@@ -5006,7 +5001,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
- {
- 	struct inode_security_struct *isec =
- 		inode_security_novalidate(SOCK_INODE(parent));
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
- 	    sk->sk_family == PF_UNIX)
-@@ -5021,7 +5016,7 @@ static void selinux_sock_graft(struct sock *sk, struct socket *parent)
- static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
- 				      struct sk_buff *skb)
- {
--	struct sk_security_struct *sksec = ep->base.sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(ep->base.sk);
- 	struct common_audit_data ad;
- 	struct lsm_network_audit net = {0,};
- 	u8 peerlbl_active;
-@@ -5172,8 +5167,8 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
- static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
- 				  struct sock *newsk)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
--	struct sk_security_struct *newsksec = newsk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
-+	struct sk_security_struct *newsksec = selinux_sock(newsk);
- 
- 	/* If policy does not support SECCLASS_SCTP_SOCKET then call
- 	 * the non-sctp clone version.
-@@ -5190,7 +5185,7 @@ static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
- static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
- 				     struct request_sock *req)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	int err;
- 	u16 family = req->rsk_ops->family;
- 	u32 connsid;
-@@ -5211,7 +5206,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
- static void selinux_inet_csk_clone(struct sock *newsk,
- 				   const struct request_sock *req)
- {
--	struct sk_security_struct *newsksec = newsk->sk_security;
-+	struct sk_security_struct *newsksec = selinux_sock(newsk);
- 
- 	newsksec->sid = req->secid;
- 	newsksec->peer_sid = req->peer_secid;
-@@ -5228,7 +5223,7 @@ static void selinux_inet_csk_clone(struct sock *newsk,
- static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
- {
- 	u16 family = sk->sk_family;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 	/* handle mapped IPv4 packets arriving via IPv6 sockets */
- 	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
-@@ -5312,7 +5307,7 @@ static int selinux_tun_dev_attach_queue(void *security)
- static int selinux_tun_dev_attach(struct sock *sk, void *security)
- {
- 	struct tun_security_struct *tunsec = security;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 	/* we don't currently perform any NetLabel based labeling here and it
- 	 * isn't clear that we would want to do so anyway; while we could apply
-@@ -5353,7 +5348,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
- 	int err = 0;
- 	u32 perm;
- 	struct nlmsghdr *nlh;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 	if (skb->len < NLMSG_HDRLEN) {
- 		err = -EINVAL;
-@@ -5494,7 +5489,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
- 			return NF_ACCEPT;
- 
- 		/* standard practice, label using the parent socket */
--		sksec = sk->sk_security;
-+		sksec = selinux_sock(sk);
- 		sid = sksec->sid;
- 	} else
- 		sid = SECINITSID_KERNEL;
-@@ -5533,7 +5528,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
- 
- 	if (sk == NULL)
- 		return NF_ACCEPT;
--	sksec = sk->sk_security;
-+	sksec = selinux_sock(sk);
- 
- 	ad.type = LSM_AUDIT_DATA_NET;
- 	ad.u.net = &net;
-@@ -5625,7 +5620,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,
- 		u32 skb_sid;
- 		struct sk_security_struct *sksec;
- 
--		sksec = sk->sk_security;
-+		sksec = selinux_sock(sk);
- 		if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
- 			return NF_DROP;
- 		/* At this point, if the returned skb peerlbl is SECSID_NULL
-@@ -5654,7 +5649,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb,
- 	} else {
- 		/* Locally generated packet, fetch the security label from the
- 		 * associated socket. */
--		struct sk_security_struct *sksec = sk->sk_security;
-+		struct sk_security_struct *sksec = selinux_sock(sk);
- 		peer_sid = sksec->sid;
- 		secmark_perm = PACKET__SEND;
- 	}
-@@ -6633,6 +6628,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
- 	.lbs_inode = sizeof(struct inode_security_struct),
- 	.lbs_ipc = sizeof(struct ipc_security_struct),
- 	.lbs_msg_msg = sizeof(struct msg_security_struct),
-+	.lbs_sock = sizeof(struct sk_security_struct),
- 	.lbs_superblock = sizeof(struct superblock_security_struct),
- };
- 
-diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
-index d08d7e5d2f93..29f02b8f8f31 100644
---- a/security/selinux/include/objsec.h
-+++ b/security/selinux/include/objsec.h
-@@ -194,4 +194,9 @@ static inline struct superblock_security_struct *selinux_superblock(
- 	return superblock->s_security + selinux_blob_sizes.lbs_superblock;
- }
- 
-+static inline struct sk_security_struct *selinux_sock(const struct sock *sock)
-+{
-+	return sock->sk_security + selinux_blob_sizes.lbs_sock;
-+}
-+
- #endif /* _SELINUX_OBJSEC_H_ */
-diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
-index 186e727b737b..c40914a157b7 100644
---- a/security/selinux/netlabel.c
-+++ b/security/selinux/netlabel.c
-@@ -31,6 +31,7 @@
- #include <linux/gfp.h>
- #include <linux/ip.h>
- #include <linux/ipv6.h>
-+#include <linux/lsm_hooks.h>
- #include <net/sock.h>
- #include <net/netlabel.h>
- #include <net/ip.h>
-@@ -81,7 +82,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
- static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
- {
- 	int rc;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	struct netlbl_lsm_secattr *secattr;
- 
- 	if (sksec->nlbl_secattr != NULL)
-@@ -114,7 +115,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
- 							const struct sock *sk,
- 							u32 sid)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
- 
- 	if (secattr == NULL)
-@@ -249,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
- 	 * being labeled by it's parent socket, if it is just exit */
- 	sk = skb_to_full_sk(skb);
- 	if (sk != NULL) {
--		struct sk_security_struct *sksec = sk->sk_security;
-+		struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 		if (sksec->nlbl_state != NLBL_REQSKB)
- 			return 0;
-@@ -287,7 +288,7 @@ int selinux_netlbl_sctp_assoc_request(struct sctp_endpoint *ep,
- {
- 	int rc;
- 	struct netlbl_lsm_secattr secattr;
--	struct sk_security_struct *sksec = ep->base.sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(ep->base.sk);
- 	struct sockaddr *addr;
- 	struct sockaddr_in addr4;
- #if IS_ENABLED(CONFIG_IPV6)
-@@ -370,7 +371,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
-  */
- void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 	if (family == PF_INET)
- 		sksec->nlbl_state = NLBL_LABELED;
-@@ -388,8 +389,8 @@ void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
-  */
- void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
--	struct sk_security_struct *newsksec = newsk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
-+	struct sk_security_struct *newsksec = selinux_sock(newsk);
- 
- 	newsksec->nlbl_state = sksec->nlbl_state;
- }
-@@ -407,7 +408,7 @@ void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
- int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
- {
- 	int rc;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	struct netlbl_lsm_secattr *secattr;
- 
- 	if (family != PF_INET && family != PF_INET6)
-@@ -522,7 +523,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
- {
- 	int rc = 0;
- 	struct sock *sk = sock->sk;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	struct netlbl_lsm_secattr secattr;
- 
- 	if (selinux_netlbl_option(level, optname) &&
-@@ -560,7 +561,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
- 						struct sockaddr *addr)
- {
- 	int rc;
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 	struct netlbl_lsm_secattr *secattr;
- 
- 	/* connected sockets are allowed to disconnect when the address family
-@@ -599,7 +600,7 @@ static int selinux_netlbl_socket_connect_helper(struct sock *sk,
- int selinux_netlbl_socket_connect_locked(struct sock *sk,
- 					 struct sockaddr *addr)
- {
--	struct sk_security_struct *sksec = sk->sk_security;
-+	struct sk_security_struct *sksec = selinux_sock(sk);
- 
- 	if (sksec->nlbl_state != NLBL_REQSKB &&
- 	    sksec->nlbl_state != NLBL_CONNLABELED)
-diff --git a/security/smack/smack.h b/security/smack/smack.h
-index caecbcba9942..4ac4bf3310d7 100644
---- a/security/smack/smack.h
-+++ b/security/smack/smack.h
-@@ -375,6 +375,11 @@ static inline struct smack_known **smack_ipc(const struct kern_ipc_perm *ipc)
- 	return ipc->security + smack_blob_sizes.lbs_ipc;
- }
- 
-+static inline struct socket_smack *smack_sock(const struct sock *sock)
-+{
-+	return sock->sk_security + smack_blob_sizes.lbs_sock;
-+}
-+
- static inline struct superblock_smack *smack_superblock(
- 					const struct super_block *superblock)
- {
+@@ -7101,6 +7101,11 @@ static int selinux_perf_event_write(struct perf_event *event)
+ }
+ #endif
+ 
++static struct lsm_id selinux_lsmid __lsm_ro_after_init = {
++	.lsm  = "selinux",
++	.slot = LSMBLOB_NEEDED
++};
++
+ /*
+  * IMPORTANT NOTE: When adding new hooks, please be careful to keep this order:
+  * 1. any hooks that don't belong to (2.) or (3.) below,
+@@ -7414,7 +7419,8 @@ static __init int selinux_init(void)
+ 
+ 	hashtab_cache_init();
+ 
+-	security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
++	security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks),
++			   &selinux_lsmid);
+ 
+ 	if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
+ 		panic("SELinux: Unable to register AVC netcache callback\n");
 diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
-index 807eff2ccce9..fd69e1bd841b 100644
+index 1ee0bf1493f6..5c10ad27be37 100644
 --- a/security/smack/smack_lsm.c
 +++ b/security/smack/smack_lsm.c
-@@ -1439,7 +1439,7 @@ static int smack_inode_getsecurity(struct inode *inode,
- 		if (sock == NULL || sock->sk == NULL)
- 			return -EOPNOTSUPP;
- 
--		ssp = sock->sk->sk_security;
-+		ssp = smack_sock(sock->sk);
- 
- 		if (strcmp(name, XATTR_SMACK_IPIN) == 0)
- 			isp = ssp->smk_in;
-@@ -1821,7 +1821,7 @@ static int smack_file_receive(struct file *file)
- 
- 	if (inode->i_sb->s_magic == SOCKFS_MAGIC) {
- 		sock = SOCKET_I(inode);
--		ssp = sock->sk->sk_security;
-+		ssp = smack_sock(sock->sk);
- 		tsp = smack_cred(current_cred());
- 		/*
- 		 * If the receiving process can't write to the
-@@ -2231,11 +2231,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
- static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
- {
- 	struct smack_known *skp = smk_of_current();
--	struct socket_smack *ssp;
--
--	ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
--	if (ssp == NULL)
--		return -ENOMEM;
-+	struct socket_smack *ssp = smack_sock(sk);
- 
- 	/*
- 	 * Sockets created by kernel threads receive web label.
-@@ -2249,11 +2245,10 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
- 	}
- 	ssp->smk_packet = NULL;
- 
--	sk->sk_security = ssp;
--
- 	return 0;
- }
- 
-+#ifdef SMACK_IPV6_PORT_LABELING
- /**
-  * smack_sk_free_security - Free a socket blob
-  * @sk: the socket
-@@ -2262,7 +2257,6 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
-  */
- static void smack_sk_free_security(struct sock *sk)
- {
--#ifdef SMACK_IPV6_PORT_LABELING
- 	struct smk_port_label *spp;
- 
- 	if (sk->sk_family == PF_INET6) {
-@@ -2275,9 +2269,8 @@ static void smack_sk_free_security(struct sock *sk)
- 		}
- 		rcu_read_unlock();
- 	}
--#endif
--	kfree(sk->sk_security);
- }
-+#endif
- 
- /**
- * smack_ipv4host_label - check host based restrictions
-@@ -2395,7 +2388,7 @@ static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
- static int smack_netlabel(struct sock *sk, int labeled)
- {
- 	struct smack_known *skp;
--	struct socket_smack *ssp = sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sk);
- 	int rc = 0;
- 
- 	/*
-@@ -2440,7 +2433,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
- 	int rc;
- 	int sk_lbl;
- 	struct smack_known *hkp;
--	struct socket_smack *ssp = sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sk);
- 	struct smk_audit_info ad;
- 
- 	rcu_read_lock();
-@@ -2516,7 +2509,7 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
- {
- 	struct sock *sk = sock->sk;
- 	struct sockaddr_in6 *addr6;
--	struct socket_smack *ssp = sock->sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sock->sk);
- 	struct smk_port_label *spp;
- 	unsigned short port = 0;
- 
-@@ -2603,7 +2596,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
- 				int act)
- {
- 	struct smk_port_label *spp;
--	struct socket_smack *ssp = sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sk);
- 	struct smack_known *skp = NULL;
- 	unsigned short port;
- 	struct smack_known *object;
-@@ -2697,7 +2690,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
- 	if (sock == NULL || sock->sk == NULL)
- 		return -EOPNOTSUPP;
- 
--	ssp = sock->sk->sk_security;
-+	ssp = smack_sock(sock->sk);
- 
- 	if (strcmp(name, XATTR_SMACK_IPIN) == 0)
- 		ssp->smk_in = skp;
-@@ -2745,7 +2738,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
- 	 * Sockets created by kernel threads receive web label.
- 	 */
- 	if (unlikely(current->flags & PF_KTHREAD)) {
--		ssp = sock->sk->sk_security;
-+		ssp = smack_sock(sock->sk);
- 		ssp->smk_in = &smack_known_web;
- 		ssp->smk_out = &smack_known_web;
- 	}
-@@ -2770,8 +2763,8 @@ static int smack_socket_post_create(struct socket *sock, int family,
- static int smack_socket_socketpair(struct socket *socka,
- 		                   struct socket *sockb)
- {
--	struct socket_smack *asp = socka->sk->sk_security;
--	struct socket_smack *bsp = sockb->sk->sk_security;
-+	struct socket_smack *asp = smack_sock(socka->sk);
-+	struct socket_smack *bsp = smack_sock(sockb->sk);
- 
- 	asp->smk_packet = bsp->smk_out;
- 	bsp->smk_packet = asp->smk_out;
-@@ -2825,7 +2818,7 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
- 		return 0;
- 
- #ifdef SMACK_IPV6_SECMARK_LABELING
--	ssp = sock->sk->sk_security;
-+	ssp = smack_sock(sock->sk);
- #endif
- 
- 	switch (sock->sk->sk_family) {
-@@ -3566,9 +3559,9 @@ static int smack_unix_stream_connect(struct sock *sock,
- {
- 	struct smack_known *skp;
- 	struct smack_known *okp;
--	struct socket_smack *ssp = sock->sk_security;
--	struct socket_smack *osp = other->sk_security;
--	struct socket_smack *nsp = newsk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sock);
-+	struct socket_smack *osp = smack_sock(other);
-+	struct socket_smack *nsp = smack_sock(newsk);
- 	struct smk_audit_info ad;
- 	int rc = 0;
- #ifdef CONFIG_AUDIT
-@@ -3614,8 +3607,8 @@ static int smack_unix_stream_connect(struct sock *sock,
-  */
- static int smack_unix_may_send(struct socket *sock, struct socket *other)
- {
--	struct socket_smack *ssp = sock->sk->sk_security;
--	struct socket_smack *osp = other->sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sock->sk);
-+	struct socket_smack *osp = smack_sock(other->sk);
- 	struct smk_audit_info ad;
- 	int rc;
- 
-@@ -3652,7 +3645,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
- 	struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
- #endif
- #ifdef SMACK_IPV6_SECMARK_LABELING
--	struct socket_smack *ssp = sock->sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sock->sk);
- 	struct smack_known *rsp;
- #endif
- 	int rc = 0;
-@@ -3817,7 +3810,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
- static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
- {
- 	struct netlbl_lsm_secattr secattr;
--	struct socket_smack *ssp = sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sk);
- 	struct smack_known *skp = NULL;
- 	int rc = 0;
- 	struct smk_audit_info ad;
-@@ -3934,7 +3927,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
- 	int slen = 1;
- 	int rc = 0;
- 
--	ssp = sock->sk->sk_security;
-+	ssp = smack_sock(sock->sk);
- 	if (ssp->smk_packet != NULL) {
- 		rcp = ssp->smk_packet->smk_known;
- 		slen = strlen(rcp) + 1;
-@@ -3984,7 +3977,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
- 
- 	switch (family) {
- 	case PF_UNIX:
--		ssp = sock->sk->sk_security;
-+		ssp = smack_sock(sock->sk);
- 		s = ssp->smk_out->smk_secid;
- 		break;
- 	case PF_INET:
-@@ -3997,7 +3990,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
- 		 * Translate what netlabel gave us.
- 		 */
- 		if (sock != NULL && sock->sk != NULL)
--			ssp = sock->sk->sk_security;
-+			ssp = smack_sock(sock->sk);
- 		netlbl_secattr_init(&secattr);
- 		rc = netlbl_skbuff_getattr(skb, family, &secattr);
- 		if (rc == 0) {
-@@ -4035,7 +4028,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
- 	    (sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
- 		return;
- 
--	ssp = sk->sk_security;
-+	ssp = smack_sock(sk);
- 	ssp->smk_in = skp;
- 	ssp->smk_out = skp;
- 	/* cssp->smk_packet is already set in smack_inet_csk_clone() */
-@@ -4055,7 +4048,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
- {
- 	u16 family = sk->sk_family;
- 	struct smack_known *skp;
--	struct socket_smack *ssp = sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sk);
- 	struct netlbl_lsm_secattr secattr;
- 	struct sockaddr_in addr;
- 	struct iphdr *hdr;
-@@ -4154,7 +4147,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
- static void smack_inet_csk_clone(struct sock *sk,
- 				 const struct request_sock *req)
- {
--	struct socket_smack *ssp = sk->sk_security;
-+	struct socket_smack *ssp = smack_sock(sk);
- 	struct smack_known *skp;
- 
- 	if (req->peer_secid != 0) {
-@@ -4558,6 +4551,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
- 	.lbs_inode = sizeof(struct inode_smack),
- 	.lbs_ipc = sizeof(struct smack_known *),
- 	.lbs_msg_msg = sizeof(struct smack_known *),
-+	.lbs_sock = sizeof(struct socket_smack),
+@@ -4694,6 +4694,11 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
  	.lbs_superblock = sizeof(struct superblock_smack),
  };
  
-@@ -4667,7 +4661,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
- 	LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream),
- 	LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
- 	LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
-+#ifdef SMACK_IPV6_PORT_LABELING
- 	LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
-+#endif
- 	LSM_HOOK_INIT(sock_graft, smack_sock_graft),
- 	LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
- 	LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
-diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
-index e36d17835d4f..701a1cc1bdcc 100644
---- a/security/smack/smack_netfilter.c
-+++ b/security/smack/smack_netfilter.c
-@@ -31,8 +31,8 @@ static unsigned int smack_ipv6_output(void *priv,
- 	struct socket_smack *ssp;
- 	struct smack_known *skp;
- 
--	if (sk && sk->sk_security) {
--		ssp = sk->sk_security;
-+	if (sk && smack_sock(sk)) {
-+		ssp = smack_sock(sk);
- 		skp = ssp->smk_out;
- 		skb->secmark = skp->smk_secid;
++static struct lsm_id smack_lsmid __lsm_ro_after_init = {
++	.lsm  = "smack",
++	.slot = LSMBLOB_NEEDED
++};
++
+ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
+ 	LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
+ 	LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
+@@ -4893,7 +4898,7 @@ static __init int smack_init(void)
+ 	/*
+ 	 * Register with LSM
+ 	 */
+-	security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack");
++	security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), &smack_lsmid);
+ 	smack_enabled = 1;
+ 
+ 	pr_info("Smack:  Initializing.\n");
+diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
+index b6a31901f289..e8f6bb9782c1 100644
+--- a/security/tomoyo/tomoyo.c
++++ b/security/tomoyo/tomoyo.c
+@@ -521,6 +521,11 @@ static void tomoyo_task_free(struct task_struct *task)
  	}
-@@ -49,8 +49,8 @@ static unsigned int smack_ipv4_output(void *priv,
- 	struct socket_smack *ssp;
- 	struct smack_known *skp;
- 
--	if (sk && sk->sk_security) {
--		ssp = sk->sk_security;
-+	if (sk && smack_sock(sk)) {
-+		ssp = smack_sock(sk);
- 		skp = ssp->smk_out;
- 		skb->secmark = skp->smk_secid;
- 	}
+ }
+ 
++static struct lsm_id tomoyo_lsmid __lsm_ro_after_init = {
++	.lsm  = "tomoyo",
++	.slot = LSMBLOB_NOT_NEEDED
++};
++
+ /*
+  * tomoyo_security_ops is a "struct security_operations" which is used for
+  * registering TOMOYO.
+@@ -573,7 +578,8 @@ static int __init tomoyo_init(void)
+ 	struct tomoyo_task *s = tomoyo_task(current);
+ 
+ 	/* register ourselves with the security framework */
+-	security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
++	security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks),
++			   &tomoyo_lsmid);
+ 	pr_info("TOMOYO Linux initialized\n");
+ 	s->domain_info = &tomoyo_kernel_domain;
+ 	atomic_inc(&tomoyo_kernel_domain.users);
+diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
+index 06e226166aab..a9639ea541f7 100644
+--- a/security/yama/yama_lsm.c
++++ b/security/yama/yama_lsm.c
+@@ -421,6 +421,11 @@ static int yama_ptrace_traceme(struct task_struct *parent)
+ 	return rc;
+ }
+ 
++static struct lsm_id yama_lsmid __lsm_ro_after_init = {
++	.lsm  = "yama",
++	.slot = LSMBLOB_NOT_NEEDED
++};
++
+ static struct security_hook_list yama_hooks[] __lsm_ro_after_init = {
+ 	LSM_HOOK_INIT(ptrace_access_check, yama_ptrace_access_check),
+ 	LSM_HOOK_INIT(ptrace_traceme, yama_ptrace_traceme),
+@@ -477,7 +482,7 @@ static inline void yama_init_sysctl(void) { }
+ static int __init yama_init(void)
+ {
+ 	pr_info("Yama: becoming mindful.\n");
+-	security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), "yama");
++	security_add_hooks(yama_hooks, ARRAY_SIZE(yama_hooks), &yama_lsmid);
+ 	yama_init_sysctl();
+ 	return 0;
+ }
 -- 
-2.19.1
+2.31.1
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help