diff options
author | Casey Schaufler <casey@schaufler-ca.com> | 2024-10-09 19:32:11 +0200 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2024-10-11 20:34:12 +0200 |
commit | 6f2f724f0e116d9ea960ff3dd645add12e60e176 (patch) | |
tree | 8f9ed2193bbc3eabb023168cc07cc4ba74db7a78 | |
parent | lsm: use lsm_prop in security_audit_rule_match (diff) | |
download | linux-6f2f724f0e116d9ea960ff3dd645add12e60e176.tar.xz linux-6f2f724f0e116d9ea960ff3dd645add12e60e176.zip |
lsm: add lsmprop_to_secctx hook
Add a new hook security_lsmprop_to_secctx() and its LSM specific
implementations. The LSM specific code will use the lsm_prop 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 <casey@schaufler-ca.com>
[PM: subject line tweak]
Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r-- | include/linux/lsm_hook_defs.h | 2 | ||||
-rw-r--r-- | include/linux/security.h | 10 | ||||
-rw-r--r-- | security/apparmor/include/secid.h | 2 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 1 | ||||
-rw-r--r-- | security/apparmor/secid.c | 25 | ||||
-rw-r--r-- | security/security.c | 21 | ||||
-rw-r--r-- | security/selinux/hooks.c | 16 | ||||
-rw-r--r-- | security/selinux/include/audit.h | 3 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 31 |
9 files changed, 100 insertions, 11 deletions
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index ea7f17e37756..ed6ea0b1ec57 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -294,6 +294,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, lsmprop_to_secctx, struct lsm_prop *prop, + 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 a4f020491e7c..f1c68e38b15d 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -535,6 +535,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, char **secdata, u32 *seclen); +int security_lsmprop_to_secctx(struct lsm_prop *prop, 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); @@ -1488,7 +1489,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_lsmprop_to_secctx(struct lsm_prop *prop, + char **secdata, u32 *seclen) { return -EOPNOTSUPP; } diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h index a912a5d5d04f..cc6d1c9f4a47 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_lsmprop_to_secctx(struct lsm_prop *prop, 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 f5d05297d59e..a58b72ed246c 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1517,6 +1517,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(lsmprop_to_secctx, apparmor_lsmprop_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..34610888559f 100644 --- a/security/apparmor/secid.c +++ b/security/apparmor/secid.c @@ -61,10 +61,10 @@ struct aa_label *aa_secid_to_label(u32 secid) return xa_load(&aa_secids, secid); } -int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +static int apparmor_label_to_secctx(struct aa_label *label, char **secdata, + u32 *seclen) { /* TODO: cache secctx and ref count so we don't have to recreate */ - struct aa_label *label = aa_secid_to_label(secid); int flags = FLAG_VIEW_SUBNS | FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT; int len; @@ -90,6 +90,27 @@ int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) return 0; } +int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) +{ + struct aa_label *label = aa_secid_to_label(secid); + + return apparmor_label_to_secctx(label, secdata, seclen); +} + +int apparmor_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, + u32 *seclen) +{ + struct aa_label *label; + + /* scaffolding */ + if (!prop->apparmor.label && prop->scaffold.secid) + label = aa_secid_to_label(prop->scaffold.secid); + else + label = prop->apparmor.label; + + return apparmor_label_to_secctx(label, secdata, seclen); +} + 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 deab7f912e12..1842f1325e77 100644 --- a/security/security.c +++ b/security/security.c @@ -4312,6 +4312,27 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) EXPORT_SYMBOL(security_secid_to_secctx); /** + * security_lsmprop_to_secctx() - Convert a lsm_prop to a secctx + * @prop: lsm specific information + * @secdata: secctx + * @seclen: secctx length + * + * Convert a @prop 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_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, + u32 *seclen) +{ + return call_int_hook(lsmprop_to_secctx, prop, secdata, seclen); +} +EXPORT_SYMBOL(security_lsmprop_to_secctx); + +/** * security_secctx_to_secid() - Convert a secctx to a secid * @secdata: secctx * @seclen: length of secctx diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index fc926d3cac6e..6e88faf3c6e5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6601,8 +6601,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_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, + u32 *seclen) +{ + u32 secid = prop->selinux.secid; + + /* scaffolding */ + if (!secid) + secid = prop->scaffold.secid; + + return selinux_secid_to_secctx(secid, secdata, seclen); } static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) @@ -7347,6 +7358,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(lsmprop_to_secctx, selinux_lsmprop_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/selinux/include/audit.h b/security/selinux/include/audit.h index c745ea2a993d..d5b0425055e4 100644 --- a/security/selinux/include/audit.h +++ b/security/selinux/include/audit.h @@ -49,7 +49,8 @@ void selinux_audit_rule_free(void *rule); * Returns 1 if the context id matches the rule, 0 if it does not, and * -errno on failure. */ -int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *rule); +int selinux_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, + void *rule); /** * selinux_audit_rule_known - check to see if rule contains selinux fields. diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 535233ad7203..66da7cbcc0b7 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4768,7 +4768,7 @@ static int smack_audit_rule_known(struct audit_krule *krule) static int smack_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, void *vrule) { - struct smack_known *skp; + struct smack_known *skp = prop->smack.skp; char *rule = vrule; if (unlikely(!rule)) { @@ -4780,10 +4780,8 @@ static int smack_audit_rule_match(struct lsm_prop *prop, u32 field, u32 op, return 0; /* scaffolding */ - if (!prop->smack.skp && prop->scaffold.secid) + if (!skp && prop->scaffold.secid) skp = smack_from_secid(prop->scaffold.secid); - else - skp = prop->smack.skp; /* * No need to do string comparisons. If a match occurs, @@ -4814,7 +4812,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 @@ -4834,6 +4831,29 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } /** + * smack_lsmprop_to_secctx - return the smack label + * @prop: includes incoming Smack data + * @secdata: destination + * @seclen: how long it is + * + * Exists for audit code. + */ +static int smack_lsmprop_to_secctx(struct lsm_prop *prop, char **secdata, + u32 *seclen) +{ + struct smack_known *skp = prop->smack.skp; + + /* scaffolding */ + if (!skp && prop->scaffold.secid) + skp = smack_from_secid(prop->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 * @seclen: how long result is @@ -5192,6 +5212,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(lsmprop_to_secctx, smack_lsmprop_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), |