@@ -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;
};
/*
@@ -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);
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 | 42 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-)