From d626a7314715ec1d4401112e87739fcf0d351af5 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Fri, 10 Nov 2023 09:22:00 -0800 Subject: [PATCH] UBUNTU: SAUCE: apparmor4.0.0 [06/90]: LSM stacking v39: LSM: Add lsmblob_to_secctx hook BugLink: http://bugs.launchpad.net/bugs/2028253 Add a new hook security_lsmblob_to_secctx() and its LSM specific implementations. The LSM specific code will use the lsmblob element allocated for that module. This allows for the possibility that more than one module may be called upon to translate a secid to a string, as can occur in the audit code. Signed-off-by: Casey Schaufler (cherry picked from commit a2b36b5dcaca7e31c3c80c9ae9198ae864d2827a https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next) Signed-off-by: Paolo Pisati --- include/linux/lsm_hook_defs.h | 2 ++ include/linux/security.h | 11 +++++++++- kernel/auditfilter.c | 1 - security/apparmor/include/secid.h | 2 ++ security/apparmor/lsm.c | 1 + security/apparmor/secid.c | 36 +++++++++++++++++++++++++++++++ security/security.c | 30 ++++++++++++++++++++++++++ security/selinux/hooks.c | 16 ++++++++++++-- security/smack/smack_lsm.c | 31 +++++++++++++++++++++----- 9 files changed, 121 insertions(+), 9 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index caac29ab1f5a..05f906835d6b 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -274,6 +274,8 @@ 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, char **secdata, u32 *seclen) +LSM_HOOK(int, -EOPNOTSUPP, lsmblob_to_secctx, struct lsmblob *blob, + char **secdata, u32 *seclen) LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen) 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 ced4c2945082..d44035f9d37e 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -509,6 +509,8 @@ 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, char **secdata, u32 *seclen); +int security_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, + u32 *seclen); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); void security_inode_invalidate_secctx(struct inode *inode); @@ -1430,7 +1432,14 @@ static inline int security_ismaclabel(const char *name) return 0; } -static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +static inline int security_secid_to_secctx(u32 secid, char **secdata, + u32 *seclen) +{ + return -EOPNOTSUPP; +} + +static inline int security_lsmblob_to_secctx(struct lsmblob *blob, + char **secdata, u32 *seclen) { return -EOPNOTSUPP; } diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 0a6a1c4c3507..08dc64bb8496 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1340,7 +1340,6 @@ int audit_filter(int msgtype, unsigned int listtype) struct audit_field *f = &e->rule.fields[i]; struct lsmblob blob = { }; pid_t pid; - u32 sid; switch (f->type) { case AUDIT_PID: diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h index a912a5d5d04f..816a425e2023 100644 --- a/security/apparmor/include/secid.h +++ b/security/apparmor/include/secid.h @@ -26,6 +26,8 @@ extern int apparmor_display_secid_mode; struct aa_label *aa_secid_to_label(u32 secid); int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); +int apparmor_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, + u32 *seclen); int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); void apparmor_release_secctx(char *secdata, u32 seclen); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index aa415bc77cf8..56b4d8ae27c0 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1512,6 +1512,7 @@ static struct security_hook_list apparmor_hooks[] __ro_after_init = { #endif LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx), + LSM_HOOK_INIT(lsmblob_to_secctx, apparmor_lsmblob_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 83d3d1e6d9dc..a7c6f5061882 100644 --- a/security/apparmor/secid.c +++ b/security/apparmor/secid.c @@ -90,6 +90,42 @@ int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return 0; } +int apparmor_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, + u32 *seclen) +{ + /* TODO: cache secctx and ref count so we don't have to recreate */ + struct aa_label *label; + int flags = FLAG_VIEW_SUBNS | FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT; + int len; + + AA_BUG(!seclen); + + /* stacking scaffolding */ + if (!blob->apparmor.label && blob->scaffold.secid) + label = aa_secid_to_label(blob->scaffold.secid); + else + label = blob->apparmor.label; + + if (!label) + return -EINVAL; + + if (apparmor_display_secid_mode) + flags |= FLAG_SHOW_MODE; + + if (secdata) + len = aa_label_asxprint(secdata, root_ns, label, + flags, GFP_ATOMIC); + else + len = aa_label_snxprint(NULL, 0, root_ns, label, flags); + + if (len < 0) + return -ENOMEM; + + *seclen = len; + + return 0; +} + int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { struct aa_label *label; diff --git a/security/security.c b/security/security.c index a02633d0ab7f..87b2fd24fa06 100644 --- a/security/security.c +++ b/security/security.c @@ -4206,6 +4206,36 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } 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 + * + * 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. + * + * Return: Return 0 on success, error on failure. + */ +int security_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, + u32 *seclen) +{ + struct security_hook_list *hp; + int rc; + + hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) { + rc = hp->hook.lsmblob_to_secctx(blob, secdata, seclen); + if (rc != LSM_RET_DEFAULT(secid_to_secctx)) + return rc; + } + + return LSM_RET_DEFAULT(secid_to_secctx); +} +EXPORT_SYMBOL(security_lsmblob_to_secctx); + /** * security_secctx_to_secid() - Convert a secctx to a secid * @secdata: secctx diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index e3ae7c33a414..81198dae049a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6605,8 +6605,19 @@ static int selinux_ismaclabel(const char *name) static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - return security_sid_to_context(secid, - secdata, seclen); + return security_sid_to_context(secid, secdata, seclen); +} + +static int selinux_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, + u32 *seclen) +{ + u32 secid = blob->selinux.secid; + + /* stacking scaffolding */ + if (!secid) + secid = blob->scaffold.secid; + + return security_sid_to_context(secid, secdata, seclen); } static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) @@ -7357,6 +7368,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = { LSM_HOOK_INIT(inode_alloc_security, selinux_inode_alloc_security), LSM_HOOK_INIT(sem_alloc_security, selinux_sem_alloc_security), LSM_HOOK_INIT(secid_to_secctx, selinux_secid_to_secctx), + LSM_HOOK_INIT(lsmblob_to_secctx, selinux_lsmblob_to_secctx), LSM_HOOK_INIT(inode_getsecctx, selinux_inode_getsecctx), LSM_HOOK_INIT(sk_alloc_security, selinux_sk_alloc_security), LSM_HOOK_INIT(tun_dev_alloc_security, selinux_tun_dev_alloc_security), diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 644c925e43d1..f093db754cf2 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4739,7 +4739,7 @@ static int smack_audit_rule_known(struct audit_krule *krule) static int smack_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *vrule, int lsmid) { - struct smack_known *skp; + struct smack_known *skp = blob->smack.skp; char *rule = vrule; if (lsmid != LSM_ID_UNDEF || lsmid != LSM_ID_SMACK) @@ -4753,10 +4753,8 @@ static int smack_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, return 0; /* stacking scaffolding */ - if (!blob->smack.skp && blob->scaffold.secid) + if (!skp && blob->scaffold.secid) skp = smack_from_secid(blob->scaffold.secid); - else - skp = blob->smack.skp; /* * No need to do string comparisons. If a match occurs, @@ -4787,7 +4785,6 @@ static int smack_ismaclabel(const char *name) return (strcmp(name, XATTR_SMACK_SUFFIX) == 0); } - /** * smack_secid_to_secctx - return the smack label for a secid * @secid: incoming integer @@ -4806,6 +4803,29 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return 0; } +/** + * smack_lsmblob_to_secctx - return the smack label + * @blob: includes incoming Smack data + * @secdata: destination + * @seclen: how long it is + * + * Exists for audit code. + */ +static int smack_lsmblob_to_secctx(struct lsmblob *blob, char **secdata, + u32 *seclen) +{ + struct smack_known *skp = blob->smack.skp; + + /* 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; +} + /** * smack_secctx_to_secid - return the secid for a smack label * @secdata: smack label @@ -5164,6 +5184,7 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { LSM_HOOK_INIT(ismaclabel, smack_ismaclabel), LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx), + LSM_HOOK_INIT(lsmblob_to_secctx, smack_lsmblob_to_secctx), LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid), LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx), LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),