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@xxxxxxxxxxxxxxxx> --- include/linux/lsm_hooks.h | 2 ++ security/security.c | 42 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index e76e5cd05180..4020e13f0669 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -2029,6 +2029,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 024601db215e..af3f6a89ee88 100644 --- a/security/security.c +++ b/security/security.c @@ -472,6 +472,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) @@ -752,6 +758,14 @@ int lsm_superblock_alloc(struct super_block *sb) RC; \ }) +#define call_one_void_hook(FUNC, ...) ({ \ + struct lsm_one_hooks *LOH = current_cred()->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_cred()->security; \ @@ -2022,6 +2036,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; @@ -2068,6 +2084,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; @@ -2339,13 +2377,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.17.0