[PATCH v39 18/42] LSM: Use lsmcontext in security_lsmblob_to_secctx
From: Casey Schaufler <casey@schaufler-ca.com>
Date: 2023-12-15 22:31:02
Also in:
linux-security-module, lkml, netfilter-devel
Subsystem:
apparmor security module, audit subsystem, networking [general], networking [labeled] (netlabel, labeled ipsec, secmark), security subsystem, selinux security module, smack security module, the rest · Maintainers:
John Johansen, John Johansen, Georgia Garcia, Paul Moore, Eric Paris, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, James Morris, "Serge E. Hallyn", Stephen Smalley, Casey Schaufler, Linus Torvalds
Replace the (secctx,seclen) pointer pair with a single lsmcontext pointer to allow return of the LSM identifier along with the context and context length. This allows security_release_secctx() to know how to release the context. Callers have been modified to use or save the returned data from the new structure. security_lsmblob_to_secctx() will now return the length value on success instead of 0. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Cc: netdev@vger.kernel.org Cc: audit@vger.kernel.org Cc: netfilter-devel@vger.kernel.org Cc: Todd Kjos <redacted> --- include/linux/lsm_hook_defs.h | 2 +- include/linux/security.h | 5 ++--- kernel/audit.c | 9 ++++----- kernel/auditsc.c | 17 ++++++----------- net/netlabel/netlabel_user.c | 3 +-- security/apparmor/include/secid.h | 3 +-- security/apparmor/secid.c | 14 ++++++++------ security/security.c | 24 +++++++++++------------- security/selinux/hooks.c | 18 +++++++++++++++--- security/smack/smack_lsm.c | 16 ++++++++++------ 10 files changed, 59 insertions(+), 52 deletions(-)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 8e0155ac6697..339a4559daf8 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h@@ -275,7 +275,7 @@ LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size) LSM_HOOK(int, 0, ismaclabel, const char *name) LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, struct lsmcontext *cp) LSM_HOOK(int, -EOPNOTSUPP, lsmblob_to_secctx, struct lsmblob *blob, - char **secdata, u32 *seclen) + struct lsmcontext *cp) LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsmcontext *cp) LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode)
diff --git a/include/linux/security.h b/include/linux/security.h
index 03b79089eaf7..2a0615a62125 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h@@ -563,8 +563,7 @@ int security_setprocattr(int lsmid, const char *name, void *value, size_t size); int security_netlink_send(struct sock *sk, struct sk_buff *skb); int security_ismaclabel(const char *name); int security_secid_to_secctx(u32 secid, struct lsmcontext *cp); -int security_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, - u32 *seclen); +int security_lsmblob_to_secctx(struct lsmblob *blob, struct lsmcontext *cp); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); void security_release_secctx(struct lsmcontext *cp); void security_inode_invalidate_secctx(struct inode *inode);
@@ -1493,7 +1492,7 @@ static inline int security_secid_to_secctx(u32 secid, struct lsmcontext *cp) } static inline int security_lsmblob_to_secctx(struct lsmblob *blob, - char **secdata, u32 *seclen) + struct lsmcontext *cp) { return -EOPNOTSUPP; }
diff --git a/kernel/audit.c b/kernel/audit.c
index 47cfb6b20c3c..a93a710c980e 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c@@ -1462,9 +1462,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (lsmblob_is_set(&audit_sig_lsm)) { err = security_lsmblob_to_secctx(&audit_sig_lsm, - &lsmctx.context, - &lsmctx.len); - if (err) + &lsmctx); + if (err < 0) return err; } sig_data_size = struct_size(sig_data, ctx, lsmctx.len);
@@ -2175,8 +2174,8 @@ int audit_log_task_context(struct audit_buffer *ab) if (!lsmblob_is_set(&blob)) return 0; - error = security_lsmblob_to_secctx(&blob, &ctx.context, &ctx.len); - if (error) { + error = security_lsmblob_to_secctx(&blob, &ctx); + if (error < 0) { if (error != -EINVAL) goto error_path; return 0;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2874255f5f25..c37cc02ea4cc 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c@@ -1109,7 +1109,7 @@ 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 (lsmblob_is_set(blob)) { - if (security_lsmblob_to_secctx(blob, &ctx.context, &ctx.len)) { + if (security_lsmblob_to_secctx(blob, &ctx) < 0) { audit_log_format(ab, " obj=(none)"); rc = 1; } else {
@@ -1370,7 +1370,7 @@ static void audit_log_time(struct audit_context *context, struct audit_buffer ** static void show_special(struct audit_context *context, int *call_panic) { - struct lsmcontext lsmcxt; + struct lsmcontext lsmctx; struct audit_buffer *ab; int i;
@@ -1393,16 +1393,12 @@ static void show_special(struct audit_context *context, int *call_panic) from_kgid(&init_user_ns, context->ipc.gid), context->ipc.mode); if (lsmblob_is_set(&context->ipc.oblob)) { - char *ctx = NULL; - u32 len; - if (security_lsmblob_to_secctx(&context->ipc.oblob, - &ctx, &len)) { + &lsmctx) < 0) { *call_panic = 1; } else { - audit_log_format(ab, " obj=%s", ctx); - lsmcontext_init(&lsmcxt, ctx, len, 0); - security_release_secctx(&lsmcxt); + audit_log_format(ab, " obj=%s", lsmctx.context); + security_release_secctx(&lsmctx); } } if (context->ipc.has_perm) {
@@ -1563,8 +1559,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n, if (lsmblob_is_set(&n->oblob)) { struct lsmcontext ctx; - if (security_lsmblob_to_secctx(&n->oblob, &ctx.context, - &ctx.len)) { + if (security_lsmblob_to_secctx(&n->oblob, &ctx) < 0) { if (call_panic) *call_panic = 2; } else {
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index b9289a22b363..561e1e476a49 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, audit_info->sessionid); if (lsmblob_is_set(&audit_info->blob) && - security_lsmblob_to_secctx(&audit_info->blob, &ctx.context, - &ctx.len) == 0) { + security_lsmblob_to_secctx(&audit_info->blob, &ctx) >= 0) { audit_log_format(audit_buf, " subj=%s", ctx.context); security_release_secctx(&ctx); }
diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h
index b66c2d043a02..568820a11efc 100644
--- a/security/apparmor/include/secid.h
+++ b/security/apparmor/include/secid.h@@ -26,8 +26,7 @@ extern int apparmor_display_secid_mode; struct aa_label *aa_secid_to_label(u32 secid); int apparmor_secid_to_secctx(u32 secid, struct lsmcontext *cp); -int apparmor_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, - u32 *seclen); +int apparmor_lsmblob_to_secctx(struct lsmblob *blob, struct lsmcontext *cp); int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); void apparmor_release_secctx(struct lsmcontext *cp);
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c
index 55d6c54fe90e..c9b9a8d90afa 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c@@ -93,8 +93,7 @@ int apparmor_secid_to_secctx(u32 secid, struct lsmcontext *cp) return len; } -int apparmor_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, - u32 *seclen) +int apparmor_lsmblob_to_secctx(struct lsmblob *blob, struct lsmcontext *cp) { /* TODO: cache secctx and ref count so we don't have to recreate */ struct aa_label *label;
@@ -115,8 +114,8 @@ int apparmor_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, if (apparmor_display_secid_mode) flags |= FLAG_SHOW_MODE; - if (secdata) - len = aa_label_asxprint(secdata, root_ns, label, + if (cp) + len = aa_label_asxprint(&cp->context, root_ns, label, flags, GFP_ATOMIC); else len = aa_label_snxprint(NULL, 0, root_ns, label, flags);
@@ -124,9 +123,12 @@ int apparmor_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, if (len < 0) return -ENOMEM; - *seclen = len; + if (cp) { + cp->len = len; + cp->id = LSM_ID_APPARMOR; + } - return 0; + return len; } int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
diff --git a/security/security.c b/security/security.c
index 708a26a88447..e070a6cd4089 100644
--- a/security/security.c
+++ b/security/security.c@@ -4203,30 +4203,28 @@ EXPORT_SYMBOL(security_secid_to_secctx); /** * security_lsmblob_to_secctx() - Convert a lsmblob to a secctx * @blob: lsm specific information - * @secdata: secctx - * @seclen: secctx length + * @cp: the LSM context * - * Convert a @blob entry to security context. If @secdata is NULL the - * length of the result will be returned in @seclen, but no @secdata - * will be returned. This does mean that the length could change between - * calls to check the length and the next call which actually allocates - * and returns the @secdata. + * Convert a @blob entry to security context. If @cp is NULL the + * length of the result will be returned, but no data will be returned. + * This does mean that the length could change between calls to check + * the length and the next call which actually allocates and returns + * the data. * - * Return: Return 0 on success, error on failure. + * Return: Return length of data on success, error on failure. */ -int security_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, - u32 *seclen) +int security_lsmblob_to_secctx(struct lsmblob *blob, struct lsmcontext *cp) { struct security_hook_list *hp; int rc; hlist_for_each_entry(hp, &security_hook_heads.lsmblob_to_secctx, list) { - rc = hp->hook.lsmblob_to_secctx(blob, secdata, seclen); - if (rc != LSM_RET_DEFAULT(secid_to_secctx)) + rc = hp->hook.lsmblob_to_secctx(blob, cp); + if (rc != LSM_RET_DEFAULT(lsmblob_to_secctx)) return rc; } - return LSM_RET_DEFAULT(secid_to_secctx); + return LSM_RET_DEFAULT(lsmblob_to_secctx); } EXPORT_SYMBOL(security_lsmblob_to_secctx);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 37b97cf81da1..d138aa692abd 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c@@ -6583,16 +6583,28 @@ static int selinux_secid_to_secctx(u32 secid, struct lsmcontext *cp) return seclen; } -static int selinux_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, - u32 *seclen) +static int selinux_lsmblob_to_secctx(struct lsmblob *blob, + struct lsmcontext *cp) { u32 secid = blob->selinux.secid; + u32 seclen; + u32 ret; /* stacking scaffolding */ if (!secid) secid = blob->scaffold.secid; - return security_sid_to_context(secid, secdata, seclen); + if (cp) { + cp->id = LSM_ID_SELINUX; + ret = security_sid_to_context(secid, &cp->context, &cp->len); + if (ret < 0) + return ret; + return cp->len; + } + ret = security_sid_to_context(secid, NULL, &seclen); + if (ret < 0) + return ret; + return seclen; } static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d82753bc52ab..1fdd4233a9b3 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c@@ -4839,19 +4839,23 @@ static int smack_secid_to_secctx(u32 secid, struct lsmcontext *cp) * * Exists for audit code. */ -static int smack_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, - u32 *seclen) +static int smack_lsmblob_to_secctx(struct lsmblob *blob, struct lsmcontext *cp) { struct smack_known *skp = blob->smack.skp; + int len; /* stacking scaffolding */ if (!skp && blob->scaffold.secid) skp = smack_from_secid(blob->scaffold.secid); - if (secdata) - *secdata = skp->smk_known; - *seclen = strlen(skp->smk_known); - return 0; + len = strlen(skp->smk_known); + + if (cp) { + cp->context = skp->smk_known; + cp->len = len; + cp->id = LSM_ID_SMACK; + } + return len; } /**
--
2.41.0