* [PATCH 69/90] LSM: Use full security context in security_inode_setsecctx
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
The security hooks security_inode_setsecctx and security_inode_getsecctx
need to maintain the context strings for any and all LSMs that
provide contexts. This information is internal to the kernel
and volitile. If only one LSM uses this information the raw form is
used.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 108 insertions(+), 2 deletions(-)
diff --git a/security/security.c b/security/security.c
index b8c90e7c4554..05a19b28e105 100644
--- a/security/security.c
+++ b/security/security.c
@@ -425,6 +425,9 @@ static int lsm_append(char *new, char **result)
/* Base list of once-only hooks */
struct lsm_one_hooks lsm_base_one;
+/* Count of inode_[gs]etsecctx hooks */
+static int lsm_inode_secctx_count;
+
/**
* security_add_hooks - Add a modules hooks to the hook lists.
* @hooks: the hooks to add
@@ -442,6 +445,15 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
hooks[i].lsm = lsm;
hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
+ /*
+ * Keep count of the internal security context using hooks.
+ * Assume that there is a 1:1 mapping from inode_getsecctx
+ * to inode_setsecctx in the security modules.
+ */
+ if (hooks[i].head == &security_hook_heads.inode_getsecctx) {
+ lsm_inode_secctx_count++;
+ continue;
+ }
/*
* Check for the special hooks that are restricted to
* a single module to create the base set. Use the hooks
@@ -2150,15 +2162,109 @@ int security_inode_notifysecctx(struct inode *inode, struct lsm_context *cp)
}
EXPORT_SYMBOL(security_inode_notifysecctx);
+/*
+ * The inode_[gs]etsecctx functions need to proved a context
+ * for multiple security modules. If there is more than one
+ * LSM supplying hooks the format will be
+ * lsm1='value',lsm2='value'[,lsmN='value']...
+ */
+static void lsm_release_secctx(struct lsm_context *cp)
+{
+ kfree(cp->context);
+}
+
int security_inode_setsecctx(struct dentry *dentry, struct lsm_context *cp)
{
- return call_int_hook(inode_setsecctx, 0, dentry, cp);
+ struct security_hook_list *hp;
+ struct lsm_context lc;
+ char *full;
+ char *ctx;
+ char *quote;
+ int rc = 0;
+
+ if (lsm_inode_secctx_count <= 1)
+ return call_int_hook(inode_setsecctx, 0, dentry, cp);
+
+ full = kstrndup(cp->context, cp->len, GFP_KERNEL);
+ if (full == NULL)
+ return -ENOMEM;
+
+ ctx = full;
+ hlist_for_each_entry(hp, &security_hook_heads.inode_setsecctx, list) {
+ if (strncmp(ctx, hp->lsm, strlen(hp->lsm))) {
+ WARN_ONCE(1, "security_inode_setsecctx form1 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ ctx += strlen(hp->lsm);
+ if (ctx[0] != '=' || ctx[1] != '\'') {
+ WARN_ONCE(1, "security_inode_setsecctx form2 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ ctx += 2;
+ quote = strnchr(ctx, cp->len, '\'');
+ if (quote == NULL) {
+ WARN_ONCE(1, "security_inode_setsecctx form3 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ quote[0] = '\0';
+ if (quote[1] != ',' && quote[1] != '\0') {
+ WARN_ONCE(1, "security_inode_setsecctx form4 error\n");
+ rc = -EINVAL;
+ break;
+ }
+ lc.context = ctx;
+ lc.len = strlen(ctx);
+
+ ctx = quote + 2;
+
+ rc = hp->hook.inode_setsecctx(dentry, &lc);
+ if (rc)
+ break;
+ }
+
+ kfree(full);
+ return rc;
}
EXPORT_SYMBOL(security_inode_setsecctx);
int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
{
- return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, cp);
+ struct security_hook_list *hp;
+ struct lsm_context lc;
+ char *final = NULL;
+ char *tp;
+ int rc;
+
+ if (lsm_inode_secctx_count <= 1)
+ return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, cp);
+
+ hlist_for_each_entry(hp, &security_hook_heads.inode_getsecctx, list) {
+ rc = hp->hook.inode_getsecctx(inode, &lc);
+ if (rc) {
+ kfree(final);
+ return rc;
+ }
+ if (final) {
+ tp = kasprintf(GFP_KERNEL, "%s,%s='%s'", final,
+ hp->lsm, lc.context);
+ kfree(final);
+ } else
+ tp = kasprintf(GFP_KERNEL, "%s='%s'", hp->lsm,
+ lc.context);
+ security_release_secctx(&lc);
+ if (tp == NULL) {
+ kfree(final);
+ return -ENOMEM;
+ }
+ final = tp;
+ }
+ cp->context = final;
+ cp->len = strlen(final);
+ cp->release = lsm_release_secctx;
+ return 0;
}
EXPORT_SYMBOL(security_inode_getsecctx);
--
2.19.1
^ permalink raw reply related
* [PATCH 68/90] LSM: Support multiple LSMs using inode_init_security
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Refactor security_inode_init_security() so that it can
do the integrity processing for more than one LSM.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 48 +++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 19 deletions(-)
diff --git a/security/security.c b/security/security.c
index 0c749816fb7b..b8c90e7c4554 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1064,9 +1064,10 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
const initxattrs initxattrs, void *fs_data)
{
- struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
- struct xattr *lsm_xattr, *evm_xattr, *xattr;
- int ret;
+ struct security_hook_list *p;
+ struct xattr *repo;
+ int rc;
+ int i;
if (unlikely(IS_PRIVATE(inode)))
return 0;
@@ -1074,24 +1075,33 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
if (!initxattrs)
return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
dir, qstr, NULL, NULL, NULL);
- memset(new_xattrs, 0, sizeof(new_xattrs));
- lsm_xattr = new_xattrs;
- ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
- &lsm_xattr->name,
- &lsm_xattr->value,
- &lsm_xattr->value_len);
- if (ret)
- goto out;
- evm_xattr = lsm_xattr + 1;
- ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
- if (ret)
- goto out;
- ret = initxattrs(inode, new_xattrs, fs_data);
+ repo = kzalloc((LSM_COUNT * 2) * sizeof(*repo), GFP_NOFS);
+ if (repo == NULL)
+ return -ENOMEM;
+
+ i = 0;
+ rc = -EOPNOTSUPP;
+ hlist_for_each_entry(p, &security_hook_heads.inode_init_security,
+ list) {
+ rc = p->hook.inode_init_security(inode, dir, qstr,
+ &repo[i].name, &repo[i].value,
+ &repo[i].value_len);
+ if (rc)
+ goto out;
+
+ rc = evm_inode_init_security(inode, &repo[i], &repo[i + 1]);
+ if (rc)
+ goto out;
+
+ i += 2;
+ }
+ rc = initxattrs(inode, repo, fs_data);
out:
- for (xattr = new_xattrs; xattr->value != NULL; xattr++)
- kfree(xattr->value);
- return (ret == -EOPNOTSUPP) ? 0 : ret;
+ for (i-- ; i >= 0; i--)
+ kfree(repo[i].value);
+ kfree(repo);
+ return (rc == -EOPNOTSUPP) ? 0 : rc;
}
EXPORT_SYMBOL(security_inode_init_security);
--
2.19.1
^ permalink raw reply related
* [PATCH 67/90] Smack: Detect if secmarks can be safely used
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Utilize the security_secmark_refcount_in() hooks to determine
if Smack can safely assume that IP secmarks are not being used
by another LSM. Only use secmarks if they can be determined to
belong to Smack.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack.h | 15 +++++++++++++++
security/smack/smack_lsm.c | 16 +++++-----------
security/smack/smack_netfilter.c | 25 +++++++++++++++++++++++--
3 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 7cc3a3382fee..66ad1c175002 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -544,4 +544,19 @@ static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
}
#endif
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+extern bool smack_use_secmark;
+void smack_secmark_refcount_inc(void);
+
+static inline bool smk_use_secmark(void)
+{
+ return smack_use_secmark;
+}
+#else
+static inline bool smk_use_secmark(void)
+{
+ return false;
+}
+#endif
+
#endif /* _SECURITY_SMACK_H */
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index aaca4ba53032..d76aa0fc37a4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3828,7 +3828,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
*/
static struct smack_known *smack_from_skb(struct sk_buff *skb)
{
- if (skb == NULL || skb->secmark == 0)
+ if (skb == NULL || skb->secmark == 0 || !smk_use_secmark())
return NULL;
return smack_from_secid(skb->secmark);
@@ -3862,7 +3862,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
switch (family) {
case PF_INET:
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
/*
* If there is a secmark use it rather than the CIPSO label.
* If there is no secmark fall back to CIPSO.
@@ -3871,7 +3870,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
skp = smack_from_skb(skb);
if (skp)
goto access_check;
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
/*
* Translate what netlabel gave us.
*/
@@ -3885,9 +3883,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
netlbl_secattr_destroy(&secattr);
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
access_check:
-#endif
+
#ifdef CONFIG_AUDIT
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
ad.a.u.net->family = family;
@@ -4014,13 +4011,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
s = ssp->smk_out->smk_secid;
break;
case PF_INET:
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
skp = smack_from_skb(skb);
if (skp) {
s = skp->smk_secid;
break;
}
-#endif
/*
* Translate what netlabel gave us.
*/
@@ -4110,7 +4105,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
}
#endif /* CONFIG_IPV6 */
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
/*
* If there is a secmark use it rather than the CIPSO label.
* If there is no secmark fall back to CIPSO.
@@ -4119,7 +4113,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
skp = smack_from_skb(skb);
if (skp)
goto access_check;
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
@@ -4129,9 +4122,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
skp = &smack_known_huh;
netlbl_secattr_destroy(&secattr);
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
access_check:
-#endif
#ifdef CONFIG_AUDIT
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
@@ -4708,6 +4699,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
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
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+ LSM_HOOK_INIT(secmark_refcount_inc, smack_secmark_refcount_inc),
#endif
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
index 701a1cc1bdcc..ea45b173f8ca 100644
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -21,6 +21,15 @@
#include <net/net_namespace.h>
#include "smack.h"
+bool smack_use_secmark;
+static bool smack_checked_secmark;
+
+void smack_secmark_refcount_inc(void)
+{
+ smack_use_secmark = true;
+ pr_info("Smack: Using network secmarks.\n");
+}
+
#if IS_ENABLED(CONFIG_IPV6)
static unsigned int smack_ipv6_output(void *priv,
@@ -31,7 +40,13 @@ static unsigned int smack_ipv6_output(void *priv,
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && smack_sock(sk)) {
+ if (!smack_checked_secmark) {
+ security_secmark_refcount_inc();
+ security_secmark_refcount_dec();
+ smack_checked_secmark = true;
+ }
+
+ if (smack_use_secmark && sk && smack_sock(sk)) {
ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
@@ -49,7 +64,13 @@ static unsigned int smack_ipv4_output(void *priv,
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && smack_sock(sk)) {
+ if (!smack_checked_secmark) {
+ security_secmark_refcount_inc();
+ security_secmark_refcount_dec();
+ smack_checked_secmark = true;
+ }
+
+ if (smack_use_secmark && sk && smack_sock(sk)) {
ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
--
2.19.1
^ permalink raw reply related
* [PATCH 65/90] LSM: Add secmark refcounting to call_one list
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
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 | 44 +++++++++++++++++++++++++++++++++++++--
2 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 711f9b3eb265..5135b8d1d759 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2049,6 +2049,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 f99845aae595..d36e5bf594dd 100644
--- a/security/security.c
+++ b/security/security.c
@@ -459,6 +459,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)
@@ -740,6 +746,14 @@ int lsm_superblock_alloc(struct super_block *sb)
RC; \
})
+#define call_one_void_hook(FUNC, ...) ({ \
+ struct lsm_one_hooks *LOH = current->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->security; \
@@ -2010,6 +2024,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;
@@ -2056,6 +2072,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;
@@ -2075,6 +2113,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
loh->secctx_to_secid = secctx_to_secid;
loh->socket_getpeersec_stream = socket_getpeersec_stream;
loh->secmark_relabel_packet = secmark_relabel_packet;
+ loh->secmark_refcount_inc = secmark_refcount_inc;
+ loh->secmark_refcount_dec = secmark_refcount_dec;
return size;
}
@@ -2327,13 +2367,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);
--
2.19.1
^ permalink raw reply related
* [PATCH 66/90] LSM: refactor security_setprocattr
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Break the common code for setting the lsm_one hooks into
a helper function.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 124 ++++++++++++++++----------------------------
1 file changed, 45 insertions(+), 79 deletions(-)
diff --git a/security/security.c b/security/security.c
index d36e5bf594dd..0c749816fb7b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2004,12 +2004,31 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
return -EINVAL;
}
+/*
+ * The use of the secid_to_secctx memeber of the union is
+ * arbitrary. Any member would work.
+ */
+static bool lsm_add_one(union security_list_options *hook,
+ struct hlist_head *head, char *lsm, size_t size,
+ bool was)
+{
+ struct security_hook_list *hp;
+
+ hlist_for_each_entry(hp, head, list) {
+ if (size >= strlen(hp->lsm) && !strncmp(lsm, hp->lsm, size)) {
+ hook->secid_to_secctx = hp->hook.secid_to_secctx;
+ return true;
+ }
+ }
+ hook->secid_to_secctx = NULL;
+ return was;
+}
+
int security_setprocattr(const char *lsm, const char *name, void *value,
size_t size)
{
struct security_hook_list *hp;
struct lsm_one_hooks *loh = current->security;
- bool found = false;
char *s;
/*
@@ -2020,80 +2039,31 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
*s = '\0';
if (!strcmp(name, "display")) {
- union security_list_options secid_to_secctx;
- 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;
+ struct lsm_one_hooks o;
+ bool found = false;
if (size == 0 || size >= 100)
return -EINVAL;
- secid_to_secctx.secid_to_secctx = NULL;
- hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secid_to_secctx = hp->hook;
- found = true;
- break;
- }
- }
- secctx_to_secid.secctx_to_secid = NULL;
- hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secctx_to_secid = hp->hook;
- found = true;
- break;
- }
- }
- socket_getpeersec_stream.socket_getpeersec_stream = NULL;
- hlist_for_each_entry(hp,
- &security_hook_heads.socket_getpeersec_stream,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- socket_getpeersec_stream = hp->hook;
- found = true;
- break;
- }
- }
- secmark_relabel_packet.secmark_relabel_packet = NULL;
- hlist_for_each_entry(hp,
- &security_hook_heads.secmark_relabel_packet,
- list) {
- if (size >= strlen(hp->lsm) &&
- !strncmp(value, hp->lsm, size)) {
- secmark_relabel_packet = hp->hook;
- found = true;
- 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;
- }
- }
+ found = lsm_add_one(&o.secid_to_secctx,
+ &security_hook_heads.secid_to_secctx,
+ value, size, found);
+ found = lsm_add_one(&o.secctx_to_secid,
+ &security_hook_heads.secctx_to_secid,
+ value, size, found);
+ found = lsm_add_one(&o.socket_getpeersec_stream,
+ &security_hook_heads.socket_getpeersec_stream,
+ value, size, found);
+ found = lsm_add_one(&o.secmark_relabel_packet,
+ &security_hook_heads.secmark_relabel_packet,
+ value, size, found);
+ found = lsm_add_one(&o.secmark_refcount_inc,
+ &security_hook_heads.secmark_refcount_inc,
+ value, size, found);
+ found = lsm_add_one(&o.secmark_refcount_dec,
+ &security_hook_heads.secmark_refcount_dec,
+ value, size, found);
+
if (!found)
return -EINVAL;
@@ -2101,20 +2071,16 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
* The named lsm is active and supplies one or more
* of the relevant hooks. Switch to it.
*/
- s = kmemdup(value, size + 1, GFP_KERNEL);
+ s = kmemdup(value, size, GFP_KERNEL);
if (s == NULL)
return -ENOMEM;
- s[size] = '\0';
+ s[size - 1] = '\0';
if (loh->lsm)
kfree(loh->lsm);
+
+ *loh = o;
loh->lsm = s;
- loh->secid_to_secctx = secid_to_secctx;
- loh->secctx_to_secid = secctx_to_secid;
- loh->socket_getpeersec_stream = socket_getpeersec_stream;
- loh->secmark_relabel_packet = secmark_relabel_packet;
- loh->secmark_refcount_inc = secmark_refcount_inc;
- loh->secmark_refcount_dec = secmark_refcount_dec;
return size;
}
--
2.19.1
^ permalink raw reply related
* [PATCH 62/90] netfilter: Fix memory leak introduced with lsm_context
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Fix a memory leak introduced by the scaffolding around
the introduction of lsm_context structures.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
net/netfilter/nfnetlink_queue.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 4a3d4b52caef..7a095b9d0a10 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -305,14 +305,13 @@ static int nfqnl_put_sk_uidgid(struct sk_buff *skb, struct sock *sk)
return -1;
}
-static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
+static void nfqnl_get_sk_secctx(struct sk_buff *skb, struct lsm_context *cp)
{
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
struct lsm_export le;
- struct lsm_context lc = { .context = NULL, .len = 0, };
if (!skb || !sk_fullsock(skb->sk))
- return 0;
+ return;
read_lock_bh(&skb->sk->sk_callback_lock);
@@ -322,14 +321,10 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
le.flags = LSM_EXPORT_SELINUX | LSM_EXPORT_SMACK;
le.selinux = skb->secmark;
le.smack = skb->secmark;
- security_secid_to_secctx(&le, &lc);
- *secdata = lc.context;
+ security_secid_to_secctx(&le, cp);
}
read_unlock_bh(&skb->sk->sk_callback_lock);
- return lc.len;
-#else
- return 0;
#endif
}
@@ -406,7 +401,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
enum ip_conntrack_info uninitialized_var(ctinfo);
struct nfnl_ct_hook *nfnl_ct;
bool csum_verify;
- struct lsm_context lc = { .context = NULL, };
+ struct lsm_context lc;
size = nlmsg_total_size(sizeof(struct nfgenmsg))
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
@@ -472,7 +467,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
- lc.len = nfqnl_get_sk_secctx(entskb, &lc.context);
+ nfqnl_get_sk_secctx(entskb, &lc);
if (lc.len)
size += nla_total_size(lc.len);
}
@@ -635,8 +630,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
nlh->nlmsg_len = skb->len;
- if (lc.context)
- security_release_secctx(&lc);
+ security_release_secctx(&lc);
return skb;
nla_put_failure:
--
2.19.1
^ permalink raw reply related
* [PATCH 64/90] netfilter: Remove unnecessary NULL check in lsm_context
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
There is a redundant NULL check when releasing a security context.
Remove it.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
net/netfilter/nfnetlink_queue.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7a095b9d0a10..83bb44d70582 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -638,8 +638,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
kfree_skb(skb);
net_err_ratelimited("nf_queue: error creating packet message\n");
nlmsg_failure:
- if (lc.context)
- security_release_secctx(&lc);
+ security_release_secctx(&lc);
return NULL;
}
--
2.19.1
^ permalink raw reply related
* [PATCH 63/90] Smack: Consolidate secmark conversions
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Add a helper function smack_from_skb() that does all the checks
required and maps a valid secmark to a smack_known structure.
Replace the direct use of the secmark in surrounding code.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/smack/smack_lsm.c | 39 ++++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 4570e8cac1b3..aaca4ba53032 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3820,6 +3820,20 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
}
#endif /* CONFIG_IPV6 */
+/**
+ * smack_from_skb - Smack data from the secmark in an skb
+ * @skb: packet
+ *
+ * Returns smack_known of the secmark or NULL if that won't work.
+ */
+static struct smack_known *smack_from_skb(struct sk_buff *skb)
+{
+ if (skb == NULL || skb->secmark == 0)
+ return NULL;
+
+ return smack_from_secid(skb->secmark);
+}
+
/**
* smack_socket_sock_rcv_skb - Smack packet delivery access check
* @sk: socket
@@ -3854,10 +3868,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
* If there is no secmark fall back to CIPSO.
* The secmark is assumed to reflect policy better.
*/
- if (skb && skb->secmark != 0) {
- skp = smack_from_secid(skb->secmark);
+ skp = smack_from_skb(skb);
+ if (skp)
goto access_check;
- }
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
/*
* Translate what netlabel gave us.
@@ -3900,9 +3913,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
proto != IPPROTO_TCP && proto != IPPROTO_DCCP)
break;
#ifdef SMACK_IPV6_SECMARK_LABELING
- if (skb && skb->secmark != 0)
- skp = smack_from_secid(skb->secmark);
- else
+ skp = smack_from_skb(skb);
+ if (skp == NULL)
skp = smack_ipv6host_label(&sadd);
if (skp == NULL)
skp = smack_net_ambient;
@@ -4003,9 +4015,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
break;
case PF_INET:
#ifdef CONFIG_SECURITY_SMACK_NETFILTER
- s = skb->secmark;
- if (s != 0)
+ skp = smack_from_skb(skb);
+ if (skp) {
+ s = skp->smk_secid;
break;
+ }
#endif
/*
* Translate what netlabel gave us.
@@ -4022,7 +4036,9 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
break;
case PF_INET6:
#ifdef SMACK_IPV6_SECMARK_LABELING
- s = skb->secmark;
+ skp = smack_from_skb(skb);
+ if (skp)
+ s = skp->smk_secid;
#endif
break;
}
@@ -4100,10 +4116,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
* If there is no secmark fall back to CIPSO.
* The secmark is assumed to reflect policy better.
*/
- if (skb && skb->secmark != 0) {
- skp = smack_from_secid(skb->secmark);
+ skp = smack_from_skb(skb);
+ if (skp)
goto access_check;
- }
#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
netlbl_secattr_init(&secattr);
--
2.19.1
^ permalink raw reply related
* [PATCH 60/90] LSM: Add secmark_relabel_packet to the set of one call hooks
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
The secmark_relabel_packet hooks are dependent on the results
of secctx_to_secid hooks. Add secmark_relabel_packet to the set
of one call hooks, as the secid use will always match the
LSM providing the secid.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 1 +
security/security.c | 18 +++++++++++++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 0653f295897a..711f9b3eb265 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2048,6 +2048,7 @@ struct lsm_one_hooks {
union security_list_options secid_to_secctx;
union security_list_options secctx_to_secid;
union security_list_options socket_getpeersec_stream;
+ union security_list_options secmark_relabel_packet;
};
/*
diff --git a/security/security.c b/security/security.c
index 4af99077572d..f99845aae595 100644
--- a/security/security.c
+++ b/security/security.c
@@ -456,6 +456,9 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
else if (hooks[i].head ==
&security_hook_heads.socket_getpeersec_stream)
lsm_base_one.socket_getpeersec_stream = hooks[i].hook;
+ else if (hooks[i].head ==
+ &security_hook_heads.secmark_relabel_packet)
+ lsm_base_one.secmark_relabel_packet = hooks[i].hook;
else
continue;
if (lsm_base_one.lsm == NULL)
@@ -2006,6 +2009,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
union security_list_options secid_to_secctx;
union security_list_options secctx_to_secid;
union security_list_options socket_getpeersec_stream;
+ union security_list_options secmark_relabel_packet;
if (size == 0 || size >= 100)
return -EINVAL;
@@ -2041,6 +2045,17 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
break;
}
}
+ secmark_relabel_packet.secmark_relabel_packet = NULL;
+ hlist_for_each_entry(hp,
+ &security_hook_heads.secmark_relabel_packet,
+ list) {
+ if (size >= strlen(hp->lsm) &&
+ !strncmp(value, hp->lsm, size)) {
+ secmark_relabel_packet = hp->hook;
+ found = true;
+ break;
+ }
+ }
if (!found)
return -EINVAL;
@@ -2059,6 +2074,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
loh->secid_to_secctx = secid_to_secctx;
loh->secctx_to_secid = secctx_to_secid;
loh->socket_getpeersec_stream = socket_getpeersec_stream;
+ loh->secmark_relabel_packet = secmark_relabel_packet;
return size;
}
@@ -2305,7 +2321,7 @@ EXPORT_SYMBOL(security_inet_conn_established);
int security_secmark_relabel_packet(u32 secid)
{
- return call_int_hook(secmark_relabel_packet, 0, secid);
+ return call_one_int_hook(secmark_relabel_packet, 0, secid);
}
EXPORT_SYMBOL(security_secmark_relabel_packet);
--
2.19.1
^ permalink raw reply related
* [PATCH 61/90] LSM: Make getting the secmark right cleaner
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Getting the u32 secmark from the result of security_secctx_to_secid()
requires knowledge about which LSM interpreted the context. Add a
function lsm_export_one_secid() that finds the active secid in a
lsm_export structure. Use it in secmark processing.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 16 ++++++++++++++++
net/netfilter/nft_meta.c | 7 +------
net/netfilter/xt_SECMARK.c | 7 +------
3 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 0be6eadd0110..8eb849d71e9d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -117,6 +117,22 @@ static inline bool lsm_export_equal(struct lsm_export *l, struct lsm_export *m)
return true;
}
+/*
+ * After calling security_secctx_to_secid() one, and only one
+ * of the LSM fields will be set in the lsm_export. Return
+ * whichever one was set. Used to supply secmarks.
+ */
+static inline u32 lsm_export_one_secid(struct lsm_export *l)
+{
+ if (l->flags & LSM_EXPORT_SELINUX)
+ return l->selinux;
+ if (l->flags & LSM_EXPORT_SMACK)
+ return l->smack;
+ if (l->flags & LSM_EXPORT_APPARMOR)
+ return l->apparmor;
+ return 0;
+}
+
/* Text representation of LSM specific security information - a "context" */
struct lsm_context {
char *context;
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index f25b26318d72..ef8db0fb0af1 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -588,12 +588,7 @@ static int nft_secmark_compute_secid(struct nft_secmark *priv)
if (err)
return err;
- /* Use the "best" secid */
- if (le.selinux)
- tmp_secid = le.selinux;
- else
- tmp_secid = le.smack;
-
+ tmp_secid = lsm_export_one_secid(&le);
if (!tmp_secid)
return -ENOENT;
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index a06e50535194..b20753957e8d 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -67,12 +67,7 @@ static int checkentry_lsm(struct xt_secmark_target_info *info)
return err;
}
- /* Smack is cheating, using SECMARK_MODE_SEL */
- if (le.selinux)
- info->secid = le.selinux;
- else
- info->secid = le.smack;
-
+ info->secid = lsm_export_one_secid(&le);
if (!info->secid) {
pr_info_ratelimited("unable to map security context \'%s\'\n",
info->secctx);
--
2.19.1
^ permalink raw reply related
* [PATCH 58/90] LSM: Specify which LSM to display
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Create a new entry "display" in /proc/.../attr for controlling
which LSM security information is displayed for a process.
The name of an active LSM that supplies hooks for human readable
data may be written to "display" to set the value. The name of
the LSM currently in use can be read from "display".
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/proc/base.c | 1 +
security/security.c | 110 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 109 insertions(+), 2 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index ddef482f1334..7bf70e041315 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2618,6 +2618,7 @@ static const struct pid_entry attr_dir_stuff[] = {
ATTR(NULL, "fscreate", 0666),
ATTR(NULL, "keycreate", 0666),
ATTR(NULL, "sockcreate", 0666),
+ ATTR(NULL, "display", 0666),
#ifdef CONFIG_SECURITY_SMACK
DIR("smack", 0555,
proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops),
diff --git a/security/security.c b/security/security.c
index b05265ec24f0..4af99077572d 100644
--- a/security/security.c
+++ b/security/security.c
@@ -46,7 +46,9 @@ static struct kmem_cache *lsm_file_cache;
static struct kmem_cache *lsm_inode_cache;
char *lsm_names;
-static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
+static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init = {
+ .lbs_task = sizeof(struct lsm_one_hooks),
+};
/* Boot-time LSM user choice */
static __initdata const char *chosen_lsm_order;
@@ -577,6 +579,7 @@ static int lsm_task_alloc(struct task_struct *task)
task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL);
if (task->security == NULL)
return -ENOMEM;
+
return 0;
}
@@ -736,7 +739,10 @@ int lsm_superblock_alloc(struct super_block *sb)
#define call_one_int_hook(FUNC, IRC, ...) ({ \
int RC = IRC; \
- if (lsm_base_one.FUNC.FUNC) \
+ struct lsm_one_hooks *LOH = current->security; \
+ if (LOH->FUNC.FUNC) \
+ RC = LOH->FUNC.FUNC(__VA_ARGS__); \
+ else if (LOH->lsm == NULL && lsm_base_one.FUNC.FUNC) \
RC = lsm_base_one.FUNC.FUNC(__VA_ARGS__); \
RC; \
})
@@ -1569,13 +1575,22 @@ int security_file_open(struct file *file)
int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
{
+ struct lsm_one_hooks *odisplay = current->security;
+ struct lsm_one_hooks *ndisplay;
int rc = lsm_task_alloc(task);
if (rc)
return rc;
+
rc = call_int_hook(task_alloc, 0, task, clone_flags);
if (unlikely(rc))
security_task_free(task);
+ else if (odisplay) {
+ ndisplay = task->security;
+ if (ndisplay)
+ *ndisplay = *odisplay;
+ }
+
return rc;
}
@@ -1945,10 +1960,28 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name,
char **value)
{
struct security_hook_list *hp;
+ struct lsm_one_hooks *loh = current->security;
+ char *s;
+
+ if (!strcmp(name, "display")) {
+ if (loh->lsm)
+ s = loh->lsm;
+ else if (lsm_base_one.lsm)
+ s = lsm_base_one.lsm;
+ else
+ return -EINVAL;
+
+ *value = kstrdup(s, GFP_KERNEL);
+ if (*value)
+ return strlen(s);
+ return -ENOMEM;
+ }
hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) {
if (lsm != NULL && strcmp(lsm, hp->lsm))
continue;
+ if (lsm == NULL && loh->lsm && strcmp(loh->lsm, hp->lsm))
+ continue;
return hp->hook.getprocattr(p, name, value);
}
return -EINVAL;
@@ -1958,10 +1991,83 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
size_t size)
{
struct security_hook_list *hp;
+ struct lsm_one_hooks *loh = current->security;
+ bool found = false;
+ char *s;
+
+ /*
+ * End the passed name at a newline.
+ */
+ s = strnchr(value, size, '\n');
+ if (s)
+ *s = '\0';
+
+ if (!strcmp(name, "display")) {
+ union security_list_options secid_to_secctx;
+ union security_list_options secctx_to_secid;
+ union security_list_options socket_getpeersec_stream;
+
+ if (size == 0 || size >= 100)
+ return -EINVAL;
+
+ secid_to_secctx.secid_to_secctx = NULL;
+ hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx,
+ list) {
+ if (size >= strlen(hp->lsm) &&
+ !strncmp(value, hp->lsm, size)) {
+ secid_to_secctx = hp->hook;
+ found = true;
+ break;
+ }
+ }
+ secctx_to_secid.secctx_to_secid = NULL;
+ hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid,
+ list) {
+ if (size >= strlen(hp->lsm) &&
+ !strncmp(value, hp->lsm, size)) {
+ secctx_to_secid = hp->hook;
+ found = true;
+ break;
+ }
+ }
+ socket_getpeersec_stream.socket_getpeersec_stream = NULL;
+ hlist_for_each_entry(hp,
+ &security_hook_heads.socket_getpeersec_stream,
+ list) {
+ if (size >= strlen(hp->lsm) &&
+ !strncmp(value, hp->lsm, size)) {
+ socket_getpeersec_stream = hp->hook;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return -EINVAL;
+
+ /*
+ * The named lsm is active and supplies one or more
+ * of the relevant hooks. Switch to it.
+ */
+ s = kmemdup(value, size + 1, GFP_KERNEL);
+ if (s == NULL)
+ return -ENOMEM;
+ s[size] = '\0';
+
+ if (loh->lsm)
+ kfree(loh->lsm);
+ loh->lsm = s;
+ loh->secid_to_secctx = secid_to_secctx;
+ loh->secctx_to_secid = secctx_to_secid;
+ loh->socket_getpeersec_stream = socket_getpeersec_stream;
+
+ return size;
+ }
hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) {
if (lsm != NULL && strcmp(lsm, hp->lsm))
continue;
+ if (lsm == NULL && loh->lsm && strcmp(loh->lsm, hp->lsm))
+ continue;
return hp->hook.setprocattr(name, value, size);
}
return -EINVAL;
--
2.19.1
^ permalink raw reply related
* [PATCH 59/90] AppArmor: Remove the exclusive flag
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
With the inclusion of the "display" process attribute
mechanism AppArmor no longer needs to be treated as an
"exclusive" security module. Remove the flag that indicates
it is exclusive.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/apparmor/lsm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 771b0ae24a5f..a8b11a7f29fa 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1705,7 +1705,7 @@ static int __init apparmor_init(void)
DEFINE_LSM(apparmor) = {
.name = "apparmor",
- .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
+ .flags = LSM_FLAG_LEGACY_MAJOR,
.enabled = &apparmor_enabled,
.blobs = &apparmor_blob_sizes,
.init = apparmor_init,
--
2.19.1
^ permalink raw reply related
* [PATCH 56/90] LSM: Special handling for secctx lsm hooks
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Create a special set of LSM hooks for the translation
to human readable security data.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 10 ++++++++++
security/security.c | 32 ++++++++++++++++++++++++--------
2 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 014791349bbd..0653f295897a 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2040,6 +2040,16 @@ struct security_hook_list {
char *lsm;
} __randomize_layout;
+/*
+ * The set of hooks that may be selected for a specific module.
+ */
+struct lsm_one_hooks {
+ char *lsm;
+ union security_list_options secid_to_secctx;
+ union security_list_options secctx_to_secid;
+ union security_list_options socket_getpeersec_stream;
+};
+
/*
* Security blob size or offset data.
*/
diff --git a/security/security.c b/security/security.c
index ae43735575d6..b05265ec24f0 100644
--- a/security/security.c
+++ b/security/security.c
@@ -420,6 +420,9 @@ static int lsm_append(char *new, char **result)
return 0;
}
+/* Base list of once-only hooks */
+struct lsm_one_hooks lsm_base_one;
+
/**
* security_add_hooks - Add a modules hooks to the hook lists.
* @hooks: the hooks to add
@@ -436,6 +439,25 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count,
for (i = 0; i < count; i++) {
hooks[i].lsm = lsm;
hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
+
+ /*
+ * Check for the special hooks that are restricted to
+ * a single module to create the base set. Use the hooks
+ * from that module for the set, which may not be complete.
+ */
+ if (lsm_base_one.lsm && strcmp(lsm_base_one.lsm, hooks[i].lsm))
+ continue;
+ if (hooks[i].head == &security_hook_heads.secid_to_secctx)
+ lsm_base_one.secid_to_secctx = hooks[i].hook;
+ else if (hooks[i].head == &security_hook_heads.secctx_to_secid)
+ lsm_base_one.secctx_to_secid = hooks[i].hook;
+ else if (hooks[i].head ==
+ &security_hook_heads.socket_getpeersec_stream)
+ lsm_base_one.socket_getpeersec_stream = hooks[i].hook;
+ else
+ continue;
+ if (lsm_base_one.lsm == NULL)
+ lsm_base_one.lsm = kstrdup(hooks[i].lsm, GFP_KERNEL);
}
if (lsm_append(lsm, &lsm_names) < 0)
panic("%s - Cannot get early memory.\n", __func__);
@@ -714,14 +736,8 @@ int lsm_superblock_alloc(struct super_block *sb)
#define call_one_int_hook(FUNC, IRC, ...) ({ \
int RC = IRC; \
- do { \
- struct security_hook_list *P; \
- \
- hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \
- RC = P->hook.FUNC(__VA_ARGS__); \
- break; \
- } \
- } while (0); \
+ if (lsm_base_one.FUNC.FUNC) \
+ RC = lsm_base_one.FUNC.FUNC(__VA_ARGS__); \
RC; \
})
--
2.19.1
^ permalink raw reply related
* [PATCH 57/90] SELinux: Use blob offset in current_sid
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Replace the use of current_security() with a call to current_cred()
so that the blob offset can be correctly applied.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/selinux/include/objsec.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 59a3b1cd5ba9..c9a88b7a96a7 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -31,6 +31,8 @@
#include "flask.h"
#include "avc.h"
+extern struct lsm_blob_sizes selinux_blob_sizes;
+
struct task_security_struct {
u32 osid; /* SID prior to last execve */
u32 sid; /* current SID */
@@ -45,7 +47,9 @@ struct task_security_struct {
*/
static inline u32 current_sid(void)
{
- const struct task_security_struct *tsec = current_security();
+ const struct task_security_struct *tsec;
+
+ tsec = current_cred()->security + selinux_blob_sizes.lbs_cred;
return tsec->sid;
}
@@ -174,7 +178,6 @@ struct bpf_security_struct {
u32 sid; /*SID of bpf obj creater*/
};
-extern struct lsm_blob_sizes selinux_blob_sizes;
static inline struct task_security_struct *selinux_cred(const struct cred *cred)
{
return cred->security + selinux_blob_sizes.lbs_cred;
--
2.19.1
^ permalink raw reply related
* [PATCH 55/90] LSM: Remove unused macro
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
The call_one_void_hook macro is unused since the change
to how releasing a secctx was made. Remove it.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
security/security.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/security/security.c b/security/security.c
index 363647cf1ae8..ae43735575d6 100644
--- a/security/security.c
+++ b/security/security.c
@@ -698,16 +698,6 @@ int lsm_superblock_alloc(struct super_block *sb)
P->hook.FUNC(__VA_ARGS__); \
} while (0)
-#define call_one_void_hook(FUNC, ...) \
- do { \
- struct security_hook_list *P; \
- \
- hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \
- P->hook.FUNC(__VA_ARGS__); \
- break; \
- } \
- } while (0)
-
#define call_int_hook(FUNC, IRC, ...) ({ \
int RC = IRC; \
do { \
--
2.19.1
^ permalink raw reply related
* [PATCH 02/90] LSM: Infrastructure management of the sock security
From: Casey Schaufler @ 2019-04-19 0:44 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
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.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.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(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index cdc5730666d6..1dbed888dab0 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)
+{
+ return sk->sk_security + apparmor_blob_sizes.lbs_sock;
+}
+
#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), \
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 49d664ddff44..2716e7731279 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),
};
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;
diff --git a/security/security.c b/security/security.c
index 550988a0f024..e32b7180282e 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);
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.
+ */
+int lsm_sock_alloc(struct sock *sock, gfp_t priority)
+{
+ if (blob_sizes.lbs_sock == 0) {
+ sock->sk_security = NULL;
+ return 0;
+ }
+
+ sock->sk_security = kzalloc(blob_sizes.lbs_sock, priority);
+ if (sock->sk_security == NULL)
+ return -ENOMEM;
+ 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)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7478d8eda00a..f38a6f484613 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)
{
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 807eff2ccce9..fd69e1bd841b 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),
.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;
}
@@ -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;
}
--
2.19.1
^ permalink raw reply related
* [PATCH 54/90] kernfs: remove lsm_context scaffolding
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Change the parameters to kernfs_node_setsecdata from a
data/length pair to a lsm_context struct as both the function
it calls and the function that calls it want that.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/kernfs/inode.c | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 4c7da446d210..d6e25cd7bf21 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -135,20 +135,15 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
return error;
}
-static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
- u32 *secdata_len)
+static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs,
+ struct lsm_context *cp)
{
- void *old_secdata;
- size_t old_secdata_len;
+ struct lsm_context old_context;
- old_secdata = attrs->ia_context.context;
- old_secdata_len = attrs->ia_context.len;
+ old_context = attrs->ia_context;
+ attrs->ia_context = *cp;
+ *cp = old_context;
- attrs->ia_context.context = *secdata;
- attrs->ia_context.len = *secdata_len;
-
- *secdata = old_secdata;
- *secdata_len = old_secdata_len;
return 0;
}
@@ -363,7 +358,7 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
return error;
mutex_lock(&kernfs_mutex);
- error = kernfs_node_setsecdata(attrs, (void **)&lc.context, &lc.len);
+ error = kernfs_node_setsecdata(attrs, &lc);
mutex_unlock(&kernfs_mutex);
if (lc.context)
--
2.19.1
^ permalink raw reply related
* [PATCH 51/90] LSM: Add the release function to the lsm_context
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
In order to ensure that the release function for a
lsm_context matches the LSM that allocated it an element
is added to the lsm_context structure to contain a
pointer to it. This function is called in security_release_secctx
instead of relying on a value in a hook list.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 6 ------
include/linux/security.h | 1 +
security/apparmor/lsm.c | 1 -
security/apparmor/secid.c | 11 ++++++-----
security/security.c | 5 ++++-
security/selinux/hooks.c | 14 ++++++++------
security/smack/smack_lsm.c | 16 ++++++++--------
7 files changed, 27 insertions(+), 27 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 11bfa0a4f188..1d364e211639 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1329,10 +1329,6 @@
* @cp contains the security context.
* @l contains the pointer to the generated security data.
*
- * @release_secctx:
- * Release the security context.
- * @secdata contains the security context.
- *
* Security hooks for Audit
*
* @audit_rule_init:
@@ -1670,7 +1666,6 @@ union security_list_options {
int (*secid_to_secctx)(struct lsm_export *l, struct lsm_context *cp);
int (*secctx_to_secid)(const struct lsm_context *cp,
struct lsm_export *l);
- void (*release_secctx)(struct lsm_context *cp);
void (*inode_invalidate_secctx)(struct inode *inode);
int (*inode_notifysecctx)(struct inode *inode, struct lsm_context *cp);
@@ -1947,7 +1942,6 @@ struct security_hook_heads {
struct hlist_head ismaclabel;
struct hlist_head secid_to_secctx;
struct hlist_head secctx_to_secid;
- struct hlist_head release_secctx;
struct hlist_head inode_invalidate_secctx;
struct hlist_head inode_notifysecctx;
struct hlist_head inode_setsecctx;
diff --git a/include/linux/security.h b/include/linux/security.h
index 9a9de2bafa55..94c714310ab7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -121,6 +121,7 @@ static inline bool lsm_export_equal(struct lsm_export *l, struct lsm_export *m)
struct lsm_context {
char *context;
u32 len;
+ void (*release)(struct lsm_context *cp); /* frees .context */
};
static inline void lsm_context_init(struct lsm_context *cp)
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 76c409737370..771b0ae24a5f 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1225,7 +1225,6 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx),
LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid),
- LSM_HOOK_INIT(release_secctx, apparmor_release_secctx),
};
/*
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c
index 9dc17903a936..30fd4ad80948 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c
@@ -81,6 +81,11 @@ static inline void aa_export_secid(struct lsm_export *l, u32 secid)
l->apparmor = secid;
}
+void apparmor_release_secctx(struct lsm_context *cp)
+{
+ kfree(cp->context);
+}
+
int apparmor_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
{
/* TODO: cache secctx and ref count so we don't have to recreate */
@@ -105,6 +110,7 @@ int apparmor_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
return -ENOMEM;
cp->len = len;
+ cp->release = apparmor_release_secctx;
return 0;
}
@@ -122,11 +128,6 @@ int apparmor_secctx_to_secid(const struct lsm_context *cp, struct lsm_export *l)
return 0;
}
-void apparmor_release_secctx(struct lsm_context *cp)
-{
- kfree(cp->context);
-}
-
/**
* aa_alloc_secid - allocate a new secid for a profile
* @label: the label to allocate a secid for
diff --git a/security/security.c b/security/security.c
index 6588172b3ec8..c8ce190dcdda 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1987,7 +1987,10 @@ EXPORT_SYMBOL(security_secctx_to_secid);
void security_release_secctx(struct lsm_context *cp)
{
- call_one_void_hook(release_secctx, cp);
+ if (WARN_ON(cp->release == NULL))
+ return;
+ cp->release(cp);
+ lsm_context_init(cp);
}
EXPORT_SYMBOL(security_release_secctx);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7bf73493d10d..0e347a26c3d8 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2812,6 +2812,11 @@ static void selinux_inode_free_security(struct inode *inode)
inode_free_security(inode);
}
+static void selinux_release_secctx(struct lsm_context *cp)
+{
+ kfree(cp->context);
+}
+
static int selinux_dentry_init_security(struct dentry *dentry, int mode,
const struct qstr *name,
struct lsm_context *cp)
@@ -2826,6 +2831,7 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
if (rc)
return rc;
+ cp->release = selinux_release_secctx;
return security_sid_to_context(&selinux_state, newsid, &cp->context,
&cp->len);
}
@@ -6306,6 +6312,7 @@ static int selinux_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
u32 secid;
selinux_import_secid(l, &secid);
+ cp->release = selinux_release_secctx;
if (l->flags & LSM_EXPORT_LENGTH)
return security_sid_to_context(&selinux_state, secid,
NULL, &cp->len);
@@ -6325,11 +6332,6 @@ static int selinux_secctx_to_secid(const struct lsm_context *cp,
return rc;
}
-static void selinux_release_secctx(struct lsm_context *cp)
-{
- kfree(cp->context);
-}
-
static void selinux_inode_invalidate_secctx(struct inode *inode)
{
struct inode_security_struct *isec = selinux_inode(inode);
@@ -6367,6 +6369,7 @@ static int selinux_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
if (len < 0)
return len;
cp->len = len;
+ cp->release = selinux_release_secctx;
return 0;
}
#ifdef CONFIG_KEYS
@@ -6781,7 +6784,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ismaclabel, selinux_ismaclabel),
LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx),
LSM_HOOK_INIT(secctx_to_secid, selinux_secctx_to_secid),
- LSM_HOOK_INIT(release_secctx, selinux_release_secctx),
LSM_HOOK_INIT(inode_invalidate_secctx, selinux_inode_invalidate_secctx),
LSM_HOOK_INIT(inode_notifysecctx, selinux_inode_notifysecctx),
LSM_HOOK_INIT(inode_setsecctx, selinux_inode_setsecctx),
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1b5b3e421bff..e00346799cdf 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4425,6 +4425,12 @@ static int smack_ismaclabel(const char *name)
return (strcmp(name, XATTR_SMACK_SUFFIX) == 0);
}
+/*
+ * The smack_release_secctx hook does nothing
+ */
+static void smack_release_secctx(struct lsm_context *cp)
+{
+}
/**
* smack_secid_to_secctx - return the smack label for a secid
@@ -4444,6 +4450,7 @@ static int smack_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp)
cp->context = (l->flags & LSM_EXPORT_LENGTH) ? NULL : skp->smk_known;
cp->len = strlen(skp->smk_known);
+ cp->release = smack_release_secctx;
return 0;
}
@@ -4467,13 +4474,6 @@ static int smack_secctx_to_secid(const struct lsm_context *cp,
return 0;
}
-/*
- * The smack_release_secctx hook does nothing
- */
-static void smack_release_secctx(struct lsm_context *cp)
-{
-}
-
static int smack_inode_notifysecctx(struct inode *inode, struct lsm_context *cp)
{
return smack_inode_setsecurity(inode, XATTR_SMACK_SUFFIX, cp->context,
@@ -4491,6 +4491,7 @@ static int smack_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
cp->context = skp->smk_known;
cp->len = strlen(skp->smk_known);
+ cp->release = smack_release_secctx;
return 0;
}
@@ -4713,7 +4714,6 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
- LSM_HOOK_INIT(release_secctx, smack_release_secctx),
LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx),
LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),
LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx),
--
2.19.1
^ permalink raw reply related
* [PATCH 52/90] LSM: Use lsm_context in inode_setsecctx hooks
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Convert SELinux and Smack to use the lsm_context structure
instead of a context/secid pair. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 5 ++---
security/security.c | 6 +++++-
security/selinux/hooks.c | 6 ++++--
security/smack/smack_lsm.c | 5 +++--
4 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 1d364e211639..014791349bbd 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1390,8 +1390,7 @@
* Must be called with inode->i_mutex locked.
*
* @dentry contains the inode we wish to set the security context of.
- * @ctx contains the string which we wish to set in the inode.
- * @ctxlen contains the length of @ctx.
+ * @cp contains the string which we wish to set in the inode.
*
* @inode_getsecctx:
* On success, returns 0 and fills out @cp with the security
@@ -1669,7 +1668,7 @@ union security_list_options {
void (*inode_invalidate_secctx)(struct inode *inode);
int (*inode_notifysecctx)(struct inode *inode, struct lsm_context *cp);
- int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
+ int (*inode_setsecctx)(struct dentry *dentry, struct lsm_context *cp);
int (*inode_getsecctx)(struct inode *inode, struct lsm_context *cp);
#ifdef CONFIG_SECURITY_NETWORK
diff --git a/security/security.c b/security/security.c
index c8ce190dcdda..9d09c774a1e9 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2008,7 +2008,11 @@ EXPORT_SYMBOL(security_inode_notifysecctx);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
{
- return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen);
+ struct lsm_context lc;
+
+ lc.context = ctx;
+ lc.len = ctxlen;
+ return call_int_hook(inode_setsecctx, 0, dentry, &lc);
}
EXPORT_SYMBOL(security_inode_setsecctx);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 0e347a26c3d8..af0d98f4dd37 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6356,9 +6356,11 @@ static int selinux_inode_notifysecctx(struct inode *inode,
/*
* called with inode->i_mutex locked
*/
-static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
+static int selinux_inode_setsecctx(struct dentry *dentry,
+ struct lsm_context *cp)
{
- return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
+ return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, cp->context,
+ cp->len, 0);
}
static int selinux_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index e00346799cdf..4570e8cac1b3 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4480,9 +4480,10 @@ static int smack_inode_notifysecctx(struct inode *inode, struct lsm_context *cp)
cp->len, 0);
}
-static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
+static int smack_inode_setsecctx(struct dentry *dentry, struct lsm_context *cp)
{
- return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, ctx, ctxlen, 0);
+ return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, cp->context,
+ cp->len, 0);
}
static int smack_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
--
2.19.1
^ permalink raw reply related
* [PATCH 53/90] LSM: Use lsm_context in security_inode_setsecctx
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
From: Casey Schaufler <cschaufler@schaufler-ca.com>
Convert security_inode_setsecctx to use the lsm_context structure
instead of a context/secid pair. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/nfsd/nfs4proc.c | 8 ++++++--
fs/nfsd/vfs.c | 7 ++++++-
include/linux/security.h | 5 +++--
security/security.c | 8 ++------
4 files changed, 17 insertions(+), 11 deletions(-)
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 0cfd257ffdaf..5b4ea2a317ed 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -54,12 +54,16 @@
static inline void
nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
{
+ struct lsm_context lc;
struct inode *inode = d_inode(resfh->fh_dentry);
int status;
inode_lock(inode);
- status = security_inode_setsecctx(resfh->fh_dentry,
- label->data, label->len);
+
+ lsm_context_init(&lc);
+ lc.context = label->data;
+ lc.len = label->len;
+ status = security_inode_setsecctx(resfh->fh_dentry, &lc);
inode_unlock(inode);
if (status)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 7dc98e14655d..2d6dd4bb7247 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -531,6 +531,7 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
__be32 error;
int host_error;
struct dentry *dentry;
+ struct lsm_context lc;
error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR);
if (error)
@@ -539,7 +540,11 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = fhp->fh_dentry;
inode_lock(d_inode(dentry));
- host_error = security_inode_setsecctx(dentry, label->data, label->len);
+
+ lsm_context_init(&lc);
+ lc.context = label->data;
+ lc.len = label->len;
+ host_error = security_inode_setsecctx(dentry, &lc);
inode_unlock(d_inode(dentry));
return nfserrno(host_error);
}
diff --git a/include/linux/security.h b/include/linux/security.h
index 94c714310ab7..0be6eadd0110 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -439,7 +439,7 @@ void security_release_secctx(struct lsm_context *cp);
void security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, struct lsm_context *cp);
-int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
+int security_inode_setsecctx(struct dentry *dentry, struct lsm_context *cp);
int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp);
#else /* CONFIG_SECURITY */
@@ -1237,7 +1237,8 @@ static inline int security_inode_notifysecctx(struct inode *inode,
{
return -EOPNOTSUPP;
}
-static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
+static inline int security_inode_setsecctx(struct dentry *dentry,
+ struct lsm_context *cp)
{
return -EOPNOTSUPP;
}
diff --git a/security/security.c b/security/security.c
index 9d09c774a1e9..363647cf1ae8 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2006,13 +2006,9 @@ int security_inode_notifysecctx(struct inode *inode, struct lsm_context *cp)
}
EXPORT_SYMBOL(security_inode_notifysecctx);
-int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
+int security_inode_setsecctx(struct dentry *dentry, struct lsm_context *cp)
{
- struct lsm_context lc;
-
- lc.context = ctx;
- lc.len = ctxlen;
- return call_int_hook(inode_setsecctx, 0, dentry, &lc);
+ return call_int_hook(inode_setsecctx, 0, dentry, cp);
}
EXPORT_SYMBOL(security_inode_setsecctx);
--
2.19.1
^ permalink raw reply related
* [PATCH 50/90] fs: remove lsm_context scaffolding
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
The conversion from secctx/seclen pairs to the lsm_context
structure used scaffolding in kernfs and nfs. Replace the
secctx/seclen pairs in the filesystem local datastructures
with a lsm_context.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/kernfs/dir.c | 9 +++------
fs/kernfs/inode.c | 13 +++++--------
fs/kernfs/kernfs-internal.h | 3 +--
fs/nfs/inode.c | 15 ++++++---------
fs/nfs/internal.h | 8 ++++----
fs/nfs/nfs4proc.c | 27 +++++++++++----------------
fs/nfs/nfs4xdr.c | 16 +++++++++-------
include/linux/nfs4.h | 8 ++++----
8 files changed, 43 insertions(+), 56 deletions(-)
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 11672c075a8b..48506e856573 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -532,12 +532,9 @@ void kernfs_put(struct kernfs_node *kn)
kfree_const(kn->name);
if (kn->iattr) {
- if (kn->iattr->ia_secdata) {
- struct lsm_context lc; /* Scaffolding -Casey */
- lc.context = kn->iattr->ia_secdata;
- lc.len = kn->iattr->ia_secdata_len;
- security_release_secctx(&lc);
- }
+ if (kn->iattr->ia_context.context)
+ security_release_secctx(
+ &kn->iattr->ia_context);
simple_xattrs_free(&kn->iattr->xattrs);
kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
}
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 45781f0da80f..4c7da446d210 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -141,11 +141,11 @@ static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
void *old_secdata;
size_t old_secdata_len;
- old_secdata = attrs->ia_secdata;
- old_secdata_len = attrs->ia_secdata_len;
+ old_secdata = attrs->ia_context.context;
+ old_secdata_len = attrs->ia_context.len;
- attrs->ia_secdata = *secdata;
- attrs->ia_secdata_len = *secdata_len;
+ attrs->ia_context.context = *secdata;
+ attrs->ia_context.len = *secdata_len;
*secdata = old_secdata;
*secdata_len = old_secdata_len;
@@ -184,7 +184,6 @@ static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
{
struct kernfs_iattrs *attrs = kn->iattr;
- struct lsm_context lc; /* Scaffolding -Casey */
inode->i_mode = kn->mode;
if (attrs) {
@@ -193,9 +192,7 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
* persistent copy in kernfs_node.
*/
set_inode_attr(inode, &attrs->ia_iattr);
- lc.context = attrs->ia_secdata;
- lc.len = attrs->ia_secdata_len;
- security_inode_notifysecctx(inode, &lc);
+ security_inode_notifysecctx(inode, &attrs->ia_context);
}
if (kernfs_type(kn) == KERNFS_DIR)
diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
index 0b7d197a904c..2a870795bb3e 100644
--- a/fs/kernfs/kernfs-internal.h
+++ b/fs/kernfs/kernfs-internal.h
@@ -21,8 +21,7 @@
struct kernfs_iattrs {
struct iattr ia_iattr;
- void *ia_secdata;
- u32 ia_secdata_len;
+ struct lsm_context ia_context;
struct simple_xattrs xattrs;
};
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 8d0be9767b14..a9a3ec40a90c 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -340,22 +340,19 @@ static void nfs_clear_label_invalid(struct inode *inode)
void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr,
struct nfs4_label *label)
{
- struct lsm_context lc; /* Scaffolding -Casey */
int error;
if (label == NULL)
return;
if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) {
- lc.context = label->label;
- lc.len = label->len;
- error = security_inode_notifysecctx(inode, &lc);
+ error = security_inode_notifysecctx(inode, &label->context);
if (error)
printk(KERN_ERR "%s() %s %d "
"security_inode_notifysecctx() %d\n",
__func__,
- (char *)label->label,
- label->len, error);
+ label->context.context,
+ label->context.len, error);
nfs_clear_label_invalid(inode);
}
}
@@ -375,12 +372,12 @@ struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags)
if (label == NULL)
return ERR_PTR(-ENOMEM);
- label->label = kzalloc(NFS4_MAXLABELLEN, flags);
- if (label->label == NULL) {
+ label->context.context = kzalloc(NFS4_MAXLABELLEN, flags);
+ if (label->context.context == NULL) {
kfree(label);
return ERR_PTR(-ENOMEM);
}
- label->len = NFS4_MAXLABELLEN;
+ label->context.len = NFS4_MAXLABELLEN;
return label;
}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index c7cf23ae6597..63de73024b5f 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -307,20 +307,20 @@ nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src)
if (!dst || !src)
return NULL;
- if (src->len > NFS4_MAXLABELLEN)
+ if (src->context.len > NFS4_MAXLABELLEN)
return NULL;
dst->lfs = src->lfs;
dst->pi = src->pi;
- dst->len = src->len;
- memcpy(dst->label, src->label, src->len);
+ dst->context.len = src->context.len;
+ memcpy(dst->context.context, src->context.context, src->context.len);
return dst;
}
static inline void nfs4_label_free(struct nfs4_label *label)
{
if (label) {
- kfree(label->label);
+ kfree(label->context.context);
kfree(label);
}
return;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 8dee01eda643..b2480d0341f1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -113,7 +113,6 @@ static inline struct nfs4_label *
nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
struct iattr *sattr, struct nfs4_label *label)
{
- struct lsm_context lc; /* Scaffolding -Casey */
int err;
if (label == NULL)
@@ -123,9 +122,7 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
return NULL;
err = security_dentry_init_security(dentry, sattr->ia_mode,
- &dentry->d_name, &lc);
- label->label = lc.context;
- label->len = lc.len;
+ &dentry->d_name, &label->context);
if (err == 0)
return label;
@@ -134,13 +131,8 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{
- struct lsm_context lc; /* Scaffolding -Casey */
-
- if (label) {
- lc.context = label->label;
- lc.len = label->len;
- security_release_secctx(&lc);
- }
+ if (label)
+ security_release_secctx(&label->context);
}
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{
@@ -3556,7 +3548,9 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx,
int open_flags, struct iattr *attr, int *opened)
{
struct nfs4_state *state;
- struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL;
+ struct nfs4_label *label = NULL;
+ struct nfs4_label l = {0, 0,
+ .context = { .context = NULL, .len = 0, }, };
label = nfs4_label_init_security(dir, ctx->dentry, attr, &l);
@@ -5595,7 +5589,8 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf,
{
struct nfs_server *server = NFS_SERVER(inode);
struct nfs_fattr fattr;
- struct nfs4_label label = {0, 0, buflen, buf};
+ struct nfs4_label label = {0, 0,
+ .context = { .context = buf, .len = buflen, }, };
u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL };
struct nfs4_getattr_arg arg = {
@@ -5621,7 +5616,7 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf,
return ret;
if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL))
return -ENOENT;
- if (buflen < label.len)
+ if (buflen < label.context.len)
return -ERANGE;
return 0;
}
@@ -5713,8 +5708,8 @@ nfs4_set_security_label(struct inode *inode, const void *buf, size_t buflen)
ilabel.pi = 0;
ilabel.lfs = 0;
- ilabel.label = (char *)buf;
- ilabel.len = buflen;
+ ilabel.context.context = (char *)buf;
+ ilabel.context.len = buflen;
olabel = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
if (IS_ERR(olabel)) {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index cfcabc33e24d..85a527ccd6d7 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1141,7 +1141,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
}
if (label && (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL)) {
- len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
+ len += 4 + 4 + 4 + (XDR_QUADLEN(label->context.len) << 2);
bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
}
@@ -1175,8 +1175,9 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
*p++ = cpu_to_be32(label->lfs);
*p++ = cpu_to_be32(label->pi);
- *p++ = cpu_to_be32(label->len);
- p = xdr_encode_opaque_fixed(p, label->label, label->len);
+ *p++ = cpu_to_be32(label->context.len);
+ p = xdr_encode_opaque_fixed(p, label->context.context,
+ label->context.len);
}
if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
*p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
@@ -4163,8 +4164,8 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
return -EIO;
if (len < NFS4_MAXLABELLEN) {
if (label) {
- memcpy(label->label, p, len);
- label->len = len;
+ memcpy(label->context.context, p, len);
+ label->context.len = len;
label->pi = pi;
label->lfs = lfs;
status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
@@ -4174,9 +4175,10 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
printk(KERN_WARNING "%s: label too long (%u)!\n",
__func__, len);
}
- if (label && label->label)
+ if (label && label->context.context)
dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__,
- (char *)label->label, label->len, label->pi, label->lfs);
+ (char *)label->context.context, label->context.len,
+ label->pi, label->lfs);
return status;
}
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 22494d170619..1189aad71592 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/uidgid.h>
+#include <linux/security.h>
#include <uapi/linux/nfs4.h>
enum nfs4_acl_whotype {
@@ -43,10 +44,9 @@ struct nfs4_acl {
#define NFS4_MAXLABELLEN 2048
struct nfs4_label {
- uint32_t lfs;
- uint32_t pi;
- u32 len;
- char *label;
+ uint32_t lfs;
+ uint32_t pi;
+ struct lsm_context context;
};
typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
--
2.19.1
^ permalink raw reply related
* [PATCH 48/90] LSM: Use lsm_context in security_release_secctx
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Convert security_release_secctx to use the lsm_context structure
instead of a context/secid pair. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
drivers/android/binder.c | 21 +++++++--------
fs/kernfs/dir.c | 9 ++++---
fs/kernfs/inode.c | 2 +-
fs/nfs/nfs4proc.c | 9 +++++--
fs/nfsd/nfs4xdr.c | 2 +-
include/linux/security.h | 4 +--
include/net/scm.h | 10 +++----
kernel/audit.c | 27 +++++++++----------
kernel/auditsc.c | 27 +++++++++----------
net/ipv4/ip_sockglue.c | 9 +++----
net/netfilter/nf_conntrack_netlink.c | 10 +++----
net/netfilter/nf_conntrack_standalone.c | 9 +++----
net/netfilter/nfnetlink_queue.c | 28 ++++++++++---------
net/netlabel/netlabel_unlabeled.c | 36 ++++++++++++-------------
net/netlabel/netlabel_user.c | 11 ++++----
security/security.c | 10 +++----
16 files changed, 109 insertions(+), 115 deletions(-)
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 0eeb5b75da5b..c2cfef13257c 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -2874,8 +2874,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_size_t last_fixup_min_off = 0;
struct binder_context *context = proc->context;
int t_debug_id = atomic_inc_return(&binder_last_id);
- char *secctx = NULL;
- u32 secctx_sz = 0;
+ struct lsm_context lc = { .len = 0, .context = NULL, };
e = binder_transaction_log_add(&binder_transaction_log);
e->debug_id = t_debug_id;
@@ -3122,14 +3121,14 @@ static void binder_transaction(struct binder_proc *proc,
struct lsm_export le;
security_task_getsecid(proc->tsk, &le);
- ret = security_secid_to_secctx(&le, &secctx, &secctx_sz);
+ ret = security_secid_to_secctx(&le, &lc.context, &lc.len);
if (ret) {
return_error = BR_FAILED_REPLY;
return_error_param = ret;
return_error_line = __LINE__;
goto err_get_secctx_failed;
}
- extra_buffers_size += ALIGN(secctx_sz, sizeof(u64));
+ extra_buffers_size += ALIGN(lc.len, sizeof(u64));
}
trace_binder_transaction(reply, t, target_node);
@@ -3148,18 +3147,18 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer = NULL;
goto err_binder_alloc_buf_failed;
}
- if (secctx) {
+ if (lc.context) {
size_t buf_offset = ALIGN(tr->data_size, sizeof(void *)) +
ALIGN(tr->offsets_size, sizeof(void *)) +
ALIGN(extra_buffers_size, sizeof(void *)) -
- ALIGN(secctx_sz, sizeof(u64));
+ ALIGN(lc.len, sizeof(u64));
t->security_ctx = (uintptr_t)t->buffer->user_data + buf_offset;
binder_alloc_copy_to_buffer(&target_proc->alloc,
t->buffer, buf_offset,
- secctx, secctx_sz);
- security_release_secctx(secctx, secctx_sz);
- secctx = NULL;
+ lc.context, lc.len);
+ security_release_secctx(&lc);
+ lc.context = NULL;
}
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
@@ -3479,8 +3478,8 @@ static void binder_transaction(struct binder_proc *proc,
t->buffer->transaction = NULL;
binder_alloc_free_buf(&target_proc->alloc, t->buffer);
err_binder_alloc_buf_failed:
- if (secctx)
- security_release_secctx(secctx, secctx_sz);
+ if (lc.context)
+ security_release_secctx(&lc);
err_get_secctx_failed:
kfree(tcomplete);
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index b84d635567d3..11672c075a8b 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -532,9 +532,12 @@ void kernfs_put(struct kernfs_node *kn)
kfree_const(kn->name);
if (kn->iattr) {
- if (kn->iattr->ia_secdata)
- security_release_secctx(kn->iattr->ia_secdata,
- kn->iattr->ia_secdata_len);
+ if (kn->iattr->ia_secdata) {
+ struct lsm_context lc; /* Scaffolding -Casey */
+ lc.context = kn->iattr->ia_secdata;
+ lc.len = kn->iattr->ia_secdata_len;
+ security_release_secctx(&lc);
+ }
simple_xattrs_free(&kn->iattr->xattrs);
kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
}
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 41c5afc698fc..45781f0da80f 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -370,7 +370,7 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
mutex_unlock(&kernfs_mutex);
if (lc.context)
- security_release_secctx(lc.context, lc.len);
+ security_release_secctx(&lc);
return error;
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index de000649f9f3..8dee01eda643 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -134,8 +134,13 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry,
static inline void
nfs4_label_release_security(struct nfs4_label *label)
{
- if (label)
- security_release_secctx(label->label, label->len);
+ struct lsm_context lc; /* Scaffolding -Casey */
+
+ if (label) {
+ lc.context = label->label;
+ lc.len = label->len;
+ security_release_secctx(&lc);
+ }
}
static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label)
{
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1bf34730d054..3d1251bd588f 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2918,7 +2918,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
out:
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
if (lc.context)
- security_release_secctx(lc.context, lc.len);
+ security_release_secctx(&lc);
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(acl);
if (tempfh) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 3f757b2d8275..57ce9b824eef 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -433,7 +433,7 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_ismaclabel(const char *name);
int security_secid_to_secctx(struct lsm_export *l, char **secdata, u32 *seclen);
int security_secctx_to_secid(struct lsm_context *cp, struct lsm_export *l);
-void security_release_secctx(char *secdata, u32 seclen);
+void security_release_secctx(struct lsm_context *cp);
void security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, struct lsm_context *cp);
@@ -1222,7 +1222,7 @@ static inline int security_secctx_to_secid(struct lsm_context *cp,
return -EOPNOTSUPP;
}
-static inline void security_release_secctx(char *secdata, u32 seclen)
+static inline void security_release_secctx(struct lsm_context *cp);
{
}
diff --git a/include/net/scm.h b/include/net/scm.h
index b5d1c24318e3..7e242ebdd258 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -92,16 +92,16 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
#ifdef CONFIG_SECURITY_NETWORK
static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
{
- char *secdata;
- u32 seclen;
+ struct lsm_context lc;
int err;
if (test_bit(SOCK_PASSSEC, &sock->flags)) {
- err = security_secid_to_secctx(&scm->le, &secdata, &seclen);
+ err = security_secid_to_secctx(&scm->le, &lc.context, &lc.len);
if (!err) {
- put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
- security_release_secctx(secdata, seclen);
+ put_cmsg(msg, SOL_SOCKET, SCM_SECURITY,
+ lc.len, lc.context);
+ security_release_secctx(&lc);
}
}
}
diff --git a/kernel/audit.c b/kernel/audit.c
index d83d1f05c95d..269c76fefe40 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1191,8 +1191,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_buffer *ab;
u16 msg_type = nlh->nlmsg_type;
struct audit_sig_info *sig_data;
- char *ctx = NULL;
- u32 len;
+ struct lsm_context lc = { .context = NULL, .len = 0, };
err = audit_netlink_ok(skb, msg_type);
if (err)
@@ -1428,27 +1427,26 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
break;
}
case AUDIT_SIGNAL_INFO:
- len = 0;
if (lsm_export_any(&audit_sig_lsm)) {
- err = security_secid_to_secctx(&audit_sig_lsm, &ctx,
- &len);
+ err = security_secid_to_secctx(&audit_sig_lsm,
+ &lc.context, &lc.len);
if (err)
return err;
}
- sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+ sig_data = kmalloc(sizeof(*sig_data) + lc.len, GFP_KERNEL);
if (!sig_data) {
if (lsm_export_any(&audit_sig_lsm))
- security_release_secctx(ctx, len);
+ security_release_secctx(&lc);
return -ENOMEM;
}
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
if (lsm_export_any(&audit_sig_lsm)) {
- memcpy(sig_data->ctx, ctx, len);
- security_release_secctx(ctx, len);
+ memcpy(sig_data->ctx, lc.context, lc.len);
+ security_release_secctx(&lc);
}
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
- sig_data, sizeof(*sig_data) + len);
+ sig_data, sizeof(*sig_data) + lc.len);
kfree(sig_data);
break;
case AUDIT_TTY_GET: {
@@ -2070,24 +2068,23 @@ void audit_log_key(struct audit_buffer *ab, char *key)
int audit_log_task_context(struct audit_buffer *ab)
{
- char *ctx = NULL;
- unsigned len;
int error;
struct lsm_export le;
+ struct lsm_context lc = { .context = NULL, };
security_task_getsecid(current, &le);
if (!lsm_export_any(&le))
return 0;
- error = security_secid_to_secctx(&le, &ctx, &len);
+ error = security_secid_to_secctx(&le, &lc.context, &lc.len);
if (error) {
if (error != -EINVAL)
goto error_path;
return 0;
}
- audit_log_format(ab, " subj=%s", ctx);
- security_release_secctx(ctx, len);
+ audit_log_format(ab, " subj=%s", lc.context);
+ security_release_secctx(&lc);
return 0;
error_path:
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d64775f4bb1b..4dab81c7aca0 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -938,9 +938,8 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
unsigned int sessionid,
struct lsm_export *l, char *comm)
{
+ struct lsm_context lc = { .context = NULL, };
struct audit_buffer *ab;
- char *ctx = NULL;
- u32 len;
int rc = 0;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
@@ -951,12 +950,12 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
from_kuid(&init_user_ns, auid),
from_kuid(&init_user_ns, uid), sessionid);
if (lsm_export_any(l)) {
- if (security_secid_to_secctx(l, &ctx, &len)) {
+ if (security_secid_to_secctx(l, &lc.context, &lc.len)) {
audit_log_format(ab, " obj=(none)");
rc = 1;
} else {
- audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ audit_log_format(ab, " obj=%s", lc.context);
+ security_release_secctx(&lc);
}
}
audit_log_format(ab, " ocomm=");
@@ -1191,14 +1190,13 @@ static void show_special(struct audit_context *context, int *call_panic)
from_kgid(&init_user_ns, context->ipc.gid),
context->ipc.mode);
if (lsm_export_any(l)) {
- char *ctx = NULL;
- u32 len;
- if (security_secid_to_secctx(l, &ctx, &len)) {
+ struct lsm_context lc = { .context = NULL, };
+ if (security_secid_to_secctx(l, &lc.context, &lc.len)) {
audit_log_format(ab, " osid=(unknown)");
*call_panic = 1;
} else {
- audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ audit_log_format(ab, " obj=%s", lc.context);
+ security_release_secctx(&lc);
}
}
if (context->ipc.has_perm) {
@@ -1342,16 +1340,15 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
MAJOR(n->rdev),
MINOR(n->rdev));
if (lsm_export_any(&n->olsm)) {
- char *ctx = NULL;
- u32 len;
+ struct lsm_context lc;
- if (security_secid_to_secctx(&n->olsm, &ctx, &len)) {
+ if (security_secid_to_secctx(&n->olsm, &lc.context, &lc.len)) {
audit_log_format(ab, " osid=(unknown)");
if (call_panic)
*call_panic = 2;
} else {
- audit_log_format(ab, " obj=%s", ctx);
- security_release_secctx(ctx, len);
+ audit_log_format(ab, " obj=%s", lc.context);
+ security_release_secctx(&lc);
}
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index a4f37ba6dbe2..18a7fab8b2d3 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -131,20 +131,19 @@ static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
{
struct lsm_export le;
- char *secdata;
- u32 seclen;
+ struct lsm_context lc;
int err;
err = security_socket_getpeersec_dgram(NULL, skb, &le);
if (err)
return;
- err = security_secid_to_secctx(&le, &secdata, &seclen);
+ err = security_secid_to_secctx(&le, &lc.context, &lc.len);
if (err)
return;
- put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata);
- security_release_secctx(secdata, seclen);
+ put_cmsg(msg, SOL_IP, SCM_SECURITY, lc.len, lc.context);
+ security_release_secctx(&lc);
}
static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index d10cc1924e46..49bce1b085ce 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -328,16 +328,16 @@ static int ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
{
struct nlattr *nest_secctx;
- int len, ret;
- char *secctx;
+ int ret;
struct lsm_export le;
+ struct lsm_context lc;
lsm_export_init(&le);
le.flags = LSM_EXPORT_SELINUX | LSM_EXPORT_SMACK;
le.selinux = ct->secmark;
le.smack = ct->secmark;
- ret = security_secid_to_secctx(&le, &secctx, &len);
+ ret = security_secid_to_secctx(&le, &lc.context, &lc.len);
if (ret)
return 0;
@@ -346,13 +346,13 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
if (!nest_secctx)
goto nla_put_failure;
- if (nla_put_string(skb, CTA_SECCTX_NAME, secctx))
+ if (nla_put_string(skb, CTA_SECCTX_NAME, lc.context))
goto nla_put_failure;
nla_nest_end(skb, nest_secctx);
ret = 0;
nla_put_failure:
- security_release_secctx(secctx, len);
+ security_release_secctx(&lc);
return ret;
}
#else
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index d353f3efc5a5..97d16a51504b 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -173,9 +173,8 @@ static void ct_seq_stop(struct seq_file *s, void *v)
static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
{
int ret;
- u32 len;
- char *secctx;
struct lsm_export le;
+ struct lsm_context lc;
/* Whichever LSM may be using the secmark */
lsm_export_init(&le);
@@ -183,13 +182,13 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
le.selinux = ct->secmark;
le.smack = ct->secmark;
- ret = security_secid_to_secctx(&le, &secctx, &len);
+ ret = security_secid_to_secctx(&le, &lc.context, &lc.len);
if (ret)
return;
- seq_printf(s, "secctx=%s ", secctx);
+ seq_printf(s, "secctx=%s ", lc.context);
- security_release_secctx(secctx, len);
+ security_release_secctx(&lc);
}
#else
static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index a0670137477b..b70871693368 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -307,9 +307,9 @@ static int nfqnl_put_sk_uidgid(struct sk_buff *skb, struct sock *sk)
static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
{
- u32 seclen = 0;
#if IS_ENABLED(CONFIG_NETWORK_SECMARK)
struct lsm_export le;
+ struct lsm_context lc = { .context = NULL, .len = 0, };
if (!skb || !sk_fullsock(skb->sk))
return 0;
@@ -322,12 +322,15 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
le.flags = LSM_EXPORT_SELINUX | LSM_EXPORT_SMACK;
le.selinux = skb->secmark;
le.smack = skb->secmark;
- security_secid_to_secctx(&le, secdata, &seclen);
+ security_secid_to_secctx(&le, &lc.context, &lc.len);
+ *secdata = lc.context;
}
read_unlock_bh(&skb->sk->sk_callback_lock);
+ return lc.len;
+#else
+ return 0;
#endif
- return seclen;
}
static u32 nfqnl_get_bridge_size(struct nf_queue_entry *entry)
@@ -403,8 +406,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
enum ip_conntrack_info uninitialized_var(ctinfo);
struct nfnl_ct_hook *nfnl_ct;
bool csum_verify;
- char *secdata = NULL;
- u32 seclen = 0;
+ struct lsm_context lc = { .context = NULL, };
size = nlmsg_total_size(sizeof(struct nfgenmsg))
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
@@ -470,9 +472,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
if ((queue->flags & NFQA_CFG_F_SECCTX) && entskb->sk) {
- seclen = nfqnl_get_sk_secctx(entskb, &secdata);
- if (seclen)
- size += nla_total_size(seclen);
+ lc.len = nfqnl_get_sk_secctx(entskb, &lc.context);
+ if (lc.len)
+ size += nla_total_size(lc.len);
}
skb = alloc_skb(size, GFP_ATOMIC);
@@ -605,7 +607,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
nfqnl_put_sk_uidgid(skb, entskb->sk) < 0)
goto nla_put_failure;
- if (seclen && nla_put(skb, NFQA_SECCTX, seclen, secdata))
+ if (lc.len && nla_put(skb, NFQA_SECCTX, lc.len, lc.context))
goto nla_put_failure;
if (ct && nfnl_ct->build(skb, ct, ctinfo, NFQA_CT, NFQA_CT_INFO) < 0)
@@ -633,8 +635,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
}
nlh->nlmsg_len = skb->len;
- if (seclen)
- security_release_secctx(secdata, seclen);
+ if (lc.context)
+ security_release_secctx(&lc);
return skb;
nla_put_failure:
@@ -642,8 +644,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
kfree_skb(skb);
net_err_ratelimited("nf_queue: error creating packet message\n");
nlmsg_failure:
- if (seclen)
- security_release_secctx(secdata, seclen);
+ if (lc.context)
+ security_release_secctx(&lc);
return NULL;
}
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 707ea5a364b0..4c4a8f6df261 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -387,8 +387,6 @@ int netlbl_unlhsh_add(struct net *net,
struct net_device *dev;
struct netlbl_unlhsh_iface *iface;
struct audit_buffer *audit_buf = NULL;
- char *secctx = NULL;
- u32 secctx_len;
if (addr_len != sizeof(struct in_addr) &&
addr_len != sizeof(struct in6_addr))
@@ -451,9 +449,10 @@ int netlbl_unlhsh_add(struct net *net,
unlhsh_add_return:
rcu_read_unlock();
if (audit_buf != NULL) {
- if (security_secid_to_secctx(l, &secctx, &secctx_len) == 0) {
- audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ struct lsm_context lc;
+ if (security_secid_to_secctx(l, &lc.context, &lc.len) == 0) {
+ audit_log_format(audit_buf, " sec_obj=%s", lc.context);
+ security_release_secctx(&lc);
}
audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0);
audit_log_end(audit_buf);
@@ -484,8 +483,6 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
struct netlbl_unlhsh_addr4 *entry;
struct audit_buffer *audit_buf;
struct net_device *dev;
- char *secctx;
- u32 secctx_len;
spin_lock(&netlbl_unlhsh_lock);
list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -499,6 +496,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
audit_info);
if (audit_buf != NULL) {
+ struct lsm_context lc;
dev = dev_get_by_index(net, iface->ifindex);
netlbl_af4list_audit_addr(audit_buf, 1,
(dev != NULL ? dev->name : NULL),
@@ -507,9 +505,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
dev_put(dev);
if (entry != NULL &&
security_secid_to_secctx(&entry->le,
- &secctx, &secctx_len) == 0) {
- audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ &lc.context, &lc.len) == 0) {
+ audit_log_format(audit_buf, " sec_obj=%s", lc.context);
+ security_release_secctx(&lc);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
@@ -560,6 +558,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
audit_info);
if (audit_buf != NULL) {
+ struct lsm_context lc;
dev = dev_get_by_index(net, iface->ifindex);
netlbl_af6list_audit_addr(audit_buf, 1,
(dev != NULL ? dev->name : NULL),
@@ -568,9 +567,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
dev_put(dev);
if (entry != NULL &&
security_secid_to_secctx(&entry->le,
- &secctx, &secctx_len) == 0) {
- audit_log_format(audit_buf, " sec_obj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ &lc.context, &lc.len) == 0) {
+ audit_log_format(audit_buf, " sec_obj=%s", lc.context);
+ security_release_secctx(&lc);
}
audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0);
audit_log_end(audit_buf);
@@ -1082,9 +1081,8 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
struct netlbl_unlhsh_walk_arg *cb_arg = arg;
struct net_device *dev;
void *data;
- char *secctx;
- u32 secctx_len;
struct lsm_export *lep;
+ struct lsm_context lc;
data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
cb_arg->seq, &netlbl_unlabel_gnl_family,
@@ -1139,14 +1137,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
lep = (struct lsm_export *)&addr6->le;
}
- ret_val = security_secid_to_secctx(lep, &secctx, &secctx_len);
+ ret_val = security_secid_to_secctx(lep, &lc.context, &lc.len);
if (ret_val != 0)
goto list_cb_failure;
ret_val = nla_put(cb_arg->skb,
NLBL_UNLABEL_A_SECCTX,
- secctx_len,
- secctx);
- security_release_secctx(secctx, secctx_len);
+ lc.len,
+ lc.context);
+ security_release_secctx(&lc);
if (ret_val != 0)
goto list_cb_failure;
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index 2cc96305c841..0418f0935199 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -98,8 +98,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
struct netlbl_audit *audit_info)
{
struct audit_buffer *audit_buf;
- char *secctx;
- u32 secctx_len;
+ struct lsm_context lc;
if (audit_enabled == AUDIT_OFF)
return NULL;
@@ -113,10 +112,10 @@ struct audit_buffer *netlbl_audit_start_common(int type,
audit_info->sessionid);
if (lsm_export_any(&audit_info->le) &&
- security_secid_to_secctx(&audit_info->le, &secctx,
- &secctx_len) == 0) {
- audit_log_format(audit_buf, " subj=%s", secctx);
- security_release_secctx(secctx, secctx_len);
+ security_secid_to_secctx(&audit_info->le, &lc.context,
+ &lc.len) == 0) {
+ audit_log_format(audit_buf, " subj=%s", lc.context);
+ security_release_secctx(&lc);
}
return audit_buf;
diff --git a/security/security.c b/security/security.c
index 029d2f4fe48c..3da7302d20ec 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1981,7 +1981,7 @@ int security_secid_to_secctx(struct lsm_export *l, char **secdata, u32 *seclen)
if (secdata)
*secdata = lc.context;
else
- security_release_secctx(lc.context, lc.len);
+ security_release_secctx(&lc);
*seclen = lc.len;
return rc;
}
@@ -1994,13 +1994,9 @@ int security_secctx_to_secid(struct lsm_context *cp, struct lsm_export *l)
}
EXPORT_SYMBOL(security_secctx_to_secid);
-void security_release_secctx(char *secdata, u32 seclen)
+void security_release_secctx(struct lsm_context *cp)
{
- struct lsm_context lc;
-
- lc.context = secdata;
- lc.len = seclen;
- call_one_void_hook(release_secctx, &lc);
+ call_one_void_hook(release_secctx, cp);
}
EXPORT_SYMBOL(security_release_secctx);
--
2.19.1
^ permalink raw reply related
* [PATCH 45/90] LSM: Use lsm_context in security_inode_getsecctx
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
From: Casey Schaufler <cschaufler@schaufler-ca.com>
Convert security_inode_getsecctx to use the lsm_context structure
instead of a context/secid pair. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
fs/kernfs/inode.c | 11 +++++------
fs/nfsd/nfs4xdr.c | 14 ++++++--------
include/linux/security.h | 5 +++--
security/security.c | 11 ++---------
4 files changed, 16 insertions(+), 25 deletions(-)
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index 460e611b1938..41c5afc698fc 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -351,8 +351,7 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
{
struct kernfs_node *kn = inode->i_private;
struct kernfs_iattrs *attrs;
- void *secdata;
- u32 secdata_len = 0;
+ struct lsm_context lc = { .context = NULL, .len = 0, };
int error;
attrs = kernfs_iattrs(kn);
@@ -362,16 +361,16 @@ static int kernfs_security_xattr_set(const struct xattr_handler *handler,
error = security_inode_setsecurity(inode, suffix, value, size, flags);
if (error)
return error;
- error = security_inode_getsecctx(inode, &secdata, &secdata_len);
+ error = security_inode_getsecctx(inode, &lc);
if (error)
return error;
mutex_lock(&kernfs_mutex);
- error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
+ error = kernfs_node_setsecdata(attrs, (void **)&lc.context, &lc.len);
mutex_unlock(&kernfs_mutex);
- if (secdata)
- security_release_secctx(secdata, secdata_len);
+ if (lc.context)
+ security_release_secctx(lc.context, lc.len);
return error;
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 3de42a729093..1bf34730d054 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2420,8 +2420,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
__be32 status;
int err;
struct nfs4_acl *acl = NULL;
- void *context = NULL;
- int contextlen;
+ struct lsm_context lc = { .context = NULL, .len = 0, };
bool contextsupport = false;
struct nfsd4_compoundres *resp = rqstp->rq_resp;
u32 minorversion = resp->cstate.minorversion;
@@ -2477,8 +2476,7 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
if ((bmval2 & FATTR4_WORD2_SECURITY_LABEL) ||
bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
- err = security_inode_getsecctx(d_inode(dentry),
- &context, &contextlen);
+ err = security_inode_getsecctx(d_inode(dentry), &lc);
else
err = -EOPNOTSUPP;
contextsupport = (err == 0);
@@ -2907,8 +2905,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
}
if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
- status = nfsd4_encode_security_label(xdr, rqstp, context,
- contextlen);
+ status = nfsd4_encode_security_label(xdr, rqstp, lc.context,
+ lc.len);
if (status)
goto out;
}
@@ -2919,8 +2917,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
out:
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- if (context)
- security_release_secctx(context, contextlen);
+ if (lc.context)
+ security_release_secctx(lc.context, lc.len);
#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
kfree(acl);
if (tempfh) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 6b2fcca08a43..90d1ff7a2fe6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -439,7 +439,7 @@ void security_release_secctx(char *secdata, u32 seclen);
void security_inode_invalidate_secctx(struct inode *inode);
int security_inode_notifysecctx(struct inode *inode, struct lsm_context *cp);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
-int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
+int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp);
#else /* CONFIG_SECURITY */
static inline int call_lsm_notifier(enum lsm_event event, void *data)
@@ -1241,7 +1241,8 @@ static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32
{
return -EOPNOTSUPP;
}
-static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
+static inline int security_inode_getsecctx(struct inode *inode,
+ struct lsm_context *cp);
{
return -EOPNOTSUPP;
}
diff --git a/security/security.c b/security/security.c
index 89bd384c14df..b37bce99107c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2023,16 +2023,9 @@ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
}
EXPORT_SYMBOL(security_inode_setsecctx);
-int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
+int security_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
{
- struct lsm_context lc = { .context = NULL, .len = 0, };
- int rc;
-
- rc = call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, &lc);
-
- *ctx = (void *)lc.context;
- *ctxlen = lc.len;
- return rc;
+ return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, cp);
}
EXPORT_SYMBOL(security_inode_getsecctx);
--
2.19.1
^ permalink raw reply related
* [PATCH 47/90] LSM: Use lsm_context in release_secctx hooks
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Convert SELinux, Smack and AppAror to use the lsm_context structure
instead of a context/secid pair. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/lsm_hooks.h | 3 +--
security/apparmor/include/secid.h | 2 +-
security/apparmor/secid.c | 4 ++--
security/security.c | 7 +++++--
security/selinux/hooks.c | 4 ++--
security/smack/smack_lsm.c | 4 ++--
6 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index f60ec98596c8..11bfa0a4f188 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1332,7 +1332,6 @@
* @release_secctx:
* Release the security context.
* @secdata contains the security context.
- * @seclen contains the length of the security context.
*
* Security hooks for Audit
*
@@ -1671,7 +1670,7 @@ union security_list_options {
int (*secid_to_secctx)(struct lsm_export *l, struct lsm_context *cp);
int (*secctx_to_secid)(const struct lsm_context *cp,
struct lsm_export *l);
- void (*release_secctx)(char *secdata, u32 seclen);
+ void (*release_secctx)(struct lsm_context *cp);
void (*inode_invalidate_secctx)(struct inode *inode);
int (*inode_notifysecctx)(struct inode *inode, struct lsm_context *cp);
diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h
index acfcf99bff0e..a780e56d4f5b 100644
--- a/security/apparmor/include/secid.h
+++ b/security/apparmor/include/secid.h
@@ -29,7 +29,7 @@ struct aa_label *aa_secid_to_label(struct lsm_export *l);
int apparmor_secid_to_secctx(struct lsm_export *l, struct lsm_context *cp);
int apparmor_secctx_to_secid(const struct lsm_context *cp,
struct lsm_export *l);
-void apparmor_release_secctx(char *secdata, u32 seclen);
+void apparmor_release_secctx(struct lsm_context *cp);
int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c
index 35df38592b6e..46c8b9a67ac7 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c
@@ -123,9 +123,9 @@ int apparmor_secctx_to_secid(const struct lsm_context *cp, struct lsm_export *l)
return 0;
}
-void apparmor_release_secctx(char *secdata, u32 seclen)
+void apparmor_release_secctx(struct lsm_context *cp)
{
- kfree(secdata);
+ kfree(cp->context);
}
/**
diff --git a/security/security.c b/security/security.c
index 9f32865e7329..029d2f4fe48c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1989,7 +1989,6 @@ EXPORT_SYMBOL(security_secid_to_secctx);
int security_secctx_to_secid(struct lsm_context *cp, struct lsm_export *l)
{
-
lsm_export_init(l);
return call_one_int_hook(secctx_to_secid, 0, cp, l);
}
@@ -1997,7 +1996,11 @@ EXPORT_SYMBOL(security_secctx_to_secid);
void security_release_secctx(char *secdata, u32 seclen)
{
- call_one_void_hook(release_secctx, secdata, seclen);
+ struct lsm_context lc;
+
+ lc.context = secdata;
+ lc.len = seclen;
+ call_one_void_hook(release_secctx, &lc);
}
EXPORT_SYMBOL(security_release_secctx);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index fe09905d013c..332296f69f76 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6322,9 +6322,9 @@ static int selinux_secctx_to_secid(const struct lsm_context *cp,
return rc;
}
-static void selinux_release_secctx(char *secdata, u32 seclen)
+static void selinux_release_secctx(struct lsm_context *cp)
{
- kfree(secdata);
+ kfree(cp->context);
}
static void selinux_inode_invalidate_secctx(struct inode *inode)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 3d24503029e5..cf27905ccaa5 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4468,9 +4468,9 @@ static int smack_secctx_to_secid(const struct lsm_context *cp,
}
/*
- * There smack_release_secctx hook does nothing
+ * The smack_release_secctx hook does nothing
*/
-static void smack_release_secctx(char *secdata, u32 seclen)
+static void smack_release_secctx(struct lsm_context *cp)
{
}
--
2.19.1
^ permalink raw reply related
* [PATCH 46/90] LSM: Use lsm_context in security_secctx_to_secid
From: Casey Schaufler @ 2019-04-19 0:45 UTC (permalink / raw)
To: casey.schaufler, jmorris, linux-security-module, selinux; +Cc: casey
In-Reply-To: <20190419004617.64627-1-casey@schaufler-ca.com>
Convert security_secctx_to_secid to use the lsm_context structure
instead of a context/secid pair. There is some scaffolding involved
that will be removed when the related data is updated.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 6 ++----
kernel/cred.c | 5 ++++-
net/netfilter/nft_meta.c | 5 ++++-
net/netfilter/xt_SECMARK.c | 5 ++++-
net/netlabel/netlabel_unlabeled.c | 16 ++++++++--------
security/security.c | 8 ++------
6 files changed, 24 insertions(+), 21 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 90d1ff7a2fe6..3f757b2d8275 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -432,8 +432,7 @@ int security_setprocattr(const char *lsm, const char *name, void *value,
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
int security_ismaclabel(const char *name);
int security_secid_to_secctx(struct lsm_export *l, char **secdata, u32 *seclen);
-int security_secctx_to_secid(const char *secdata, u32 seclen,
- struct lsm_export *l);
+int security_secctx_to_secid(struct lsm_context *cp, struct lsm_export *l);
void security_release_secctx(char *secdata, u32 seclen);
void security_inode_invalidate_secctx(struct inode *inode);
@@ -1217,8 +1216,7 @@ static inline int security_secid_to_secctx(struct lsm_export *l,
return -EOPNOTSUPP;
}
-static inline int security_secctx_to_secid(const char *secdata,
- u32 seclen,
+static inline int security_secctx_to_secid(struct lsm_context *cp,
struct lsm_export *l)
{
return -EOPNOTSUPP;
diff --git a/kernel/cred.c b/kernel/cred.c
index 7792538b1ca6..ebae67fdd4d0 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -724,10 +724,13 @@ EXPORT_SYMBOL(set_security_override);
*/
int set_security_override_from_ctx(struct cred *new, const char *secctx)
{
+ struct lsm_context lc;
struct lsm_export le;
int ret;
- ret = security_secctx_to_secid(secctx, strlen(secctx), &le);
+ lc.context = secctx;
+ lc.len = strlen(secctx);
+ ret = security_secctx_to_secid(&lc, &le);
if (ret < 0)
return ret;
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index a1d3dab5bc25..f25b26318d72 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -577,11 +577,14 @@ static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
static int nft_secmark_compute_secid(struct nft_secmark *priv)
{
struct lsm_export le;
+ struct lsm_context lc;
u32 tmp_secid = 0;
int err;
lsm_export_init(&le);
- err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &le);
+ lc.context = priv->ctx;
+ lc.len = strlen(priv->ctx);
+ err = security_secctx_to_secid(&lc, &le);
if (err)
return err;
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 9a2a97c200a2..a06e50535194 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -50,13 +50,16 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
static int checkentry_lsm(struct xt_secmark_target_info *info)
{
struct lsm_export le;
+ struct lsm_context lc;
int err;
info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
info->secid = 0;
lsm_export_init(&le);
- err = security_secctx_to_secid(info->secctx, strlen(info->secctx), &le);
+ lc.context = info->secctx;
+ lc.len = strlen(info->secctx);
+ err = security_secctx_to_secid(&lc, &le);
if (err) {
if (err == -EINVAL)
pr_info_ratelimited("invalid security context \'%s\'\n",
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index f79ab91bf25e..707ea5a364b0 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -894,6 +894,7 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
void *mask;
u32 addr_len;
struct lsm_export le;
+ struct lsm_context lc;
struct netlbl_audit audit_info;
/* Don't allow users to add both IPv4 and IPv6 addresses for a
@@ -914,10 +915,9 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb,
if (ret_val != 0)
return ret_val;
dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]);
- ret_val = security_secctx_to_secid(
- nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
- nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
- &le);
+ lc.context = nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]);
+ lc.len = nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]);
+ ret_val = security_secctx_to_secid(&lc, &le);
if (ret_val != 0)
return ret_val;
@@ -945,6 +945,7 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
void *mask;
u32 addr_len;
struct lsm_export le;
+ struct lsm_context lc;
struct netlbl_audit audit_info;
/* Don't allow users to add both IPv4 and IPv6 addresses for a
@@ -963,10 +964,9 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb,
ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len);
if (ret_val != 0)
return ret_val;
- ret_val = security_secctx_to_secid(
- nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]),
- nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]),
- &le);
+ lc.context = nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]);
+ lc.len = nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]);
+ ret_val = security_secctx_to_secid(&lc, &le);
if (ret_val != 0)
return ret_val;
diff --git a/security/security.c b/security/security.c
index b37bce99107c..9f32865e7329 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1987,15 +1987,11 @@ int security_secid_to_secctx(struct lsm_export *l, char **secdata, u32 *seclen)
}
EXPORT_SYMBOL(security_secid_to_secctx);
-int security_secctx_to_secid(const char *secdata, u32 seclen,
- struct lsm_export *l)
+int security_secctx_to_secid(struct lsm_context *cp, struct lsm_export *l)
{
- struct lsm_context lc;
- lc.context = secdata;
- lc.len = seclen;
lsm_export_init(l);
- return call_one_int_hook(secctx_to_secid, 0, &lc, l);
+ return call_one_int_hook(secctx_to_secid, 0, cp, l);
}
EXPORT_SYMBOL(security_secctx_to_secid);
--
2.19.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox