[RFC PATCH] audit, security: allow LSMs to selectively enable audit collection
Casey Schaufler
casey at schaufler-ca.com
Fri Aug 30 15:31:31 UTC 2019
On 8/30/2019 6:44 AM, Stephen Smalley wrote:
> On 8/15/19 1:41 PM, Aaron Goidel wrote:
>> Presently, there is no way for LSMs to enable collection of supplemental
>> audit records such as path and inode information when a permission denial
>> occurs. Provide a LSM hook to allow LSMs to selectively enable collection
>> on a per-task basis, even if the audit configuration would otherwise
>> disable auditing of a task and/or contains no audit filter rules. If the
>> hook returns a non-zero result, collect all available audit information. If
>> the hook generates its own audit record, then supplemental audit
>> information will be emitted at syscall exit.
>>
>> In SELinux, we implement this hook by returning the result of a permission
>> check on the process. If the new process2:audit_enable permission is
>> allowed by the policy, then audit collection will be enabled for that
>> process. Otherwise, SELinux will defer to the audit configuration.
>
> Any feedback on this RFC patch? I know Paul provided some thoughts on the general topic of LSM/audit enablement in the other patch thread but I haven't seen any response to this patch.
Audit policy should be independent of security module policy.
I shouldn't have to change SELinux policy to enable this data
collection. I should be able to change the audit configuration
to get this if I want it.
>
>>
>> Signed-off-by: Aaron Goidel <acgoide at tycho.nsa.gov>
>> ---
>> include/linux/lsm_hooks.h | 7 +++++++
>> include/linux/security.h | 7 ++++++-
>> kernel/auditsc.c | 10 +++++++---
>> security/security.c | 5 +++++
>> security/selinux/hooks.c | 11 +++++++++++
>> security/selinux/include/classmap.h | 2 +-
>> 6 files changed, 37 insertions(+), 5 deletions(-)
>>
>> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
>> index ead98af9c602..7d70a6759621 100644
>> --- a/include/linux/lsm_hooks.h
>> +++ b/include/linux/lsm_hooks.h
>> @@ -1380,6 +1380,11 @@
>> * audit_rule_init.
>> * @lsmrule contains the allocated rule
>> *
>> + * @audit_enable:
>> + * Allow the security module to selectively enable audit collection
>> + * on permission denials based on whether or not @tsk has the
>> + * process2:audit_enable permission.
>> + *
>> * @inode_invalidate_secctx:
>> * Notify the security module that it must revalidate the security context
>> * of an inode.
>> @@ -1800,6 +1805,7 @@ union security_list_options {
>> int (*audit_rule_known)(struct audit_krule *krule);
>> int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule);
>> void (*audit_rule_free)(void *lsmrule);
>> + int (*audit_enable)(struct task_struct *tsk);
>> #endif /* CONFIG_AUDIT */
>> #ifdef CONFIG_BPF_SYSCALL
>> @@ -2043,6 +2049,7 @@ struct security_hook_heads {
>> struct hlist_head audit_rule_known;
>> struct hlist_head audit_rule_match;
>> struct hlist_head audit_rule_free;
>> + struct hlist_head audit_enable;
>> #endif /* CONFIG_AUDIT */
>> #ifdef CONFIG_BPF_SYSCALL
>> struct hlist_head bpf;
>> diff --git a/include/linux/security.h b/include/linux/security.h
>> index 7d9c1da1f659..7be66db8de4e 100644
>> --- a/include/linux/security.h
>> +++ b/include/linux/security.h
>> @@ -1719,7 +1719,7 @@ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
>> int security_audit_rule_known(struct audit_krule *krule);
>> int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule);
>> void security_audit_rule_free(void *lsmrule);
>> -
>> +int security_audit_enable(struct task_struct *tsk);
>> #else
>> static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr,
>> @@ -1742,6 +1742,11 @@ static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
>> static inline void security_audit_rule_free(void *lsmrule)
>> { }
>> +static inline int security_audit_enable(struct task_struct *tsk)
>> +{
>> + return 0;
>> +}
>> +
>> #endif /* CONFIG_SECURITY */
>> #endif /* CONFIG_AUDIT */
>> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
>> index 95ae27edd417..7e052b71bc42 100644
>> --- a/kernel/auditsc.c
>> +++ b/kernel/auditsc.c
>> @@ -906,8 +906,12 @@ int audit_alloc(struct task_struct *tsk)
>> state = audit_filter_task(tsk, &key);
>> if (state == AUDIT_DISABLED) {
>> - clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
>> - return 0;
>> + if (security_audit_enable(tsk)) {
>> + state = AUDIT_BUILD_CONTEXT;
>> + } else {
>> + clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT);
>> + return 0;
>> + }
>> }
>> if (!(context = audit_alloc_context(state))) {
>> @@ -1623,7 +1627,7 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
>> if (state == AUDIT_DISABLED)
>> return;
>> - context->dummy = !audit_n_rules;
>> + context->dummy = !audit_n_rules && !security_audit_enable(current);
>> if (!context->dummy && state == AUDIT_BUILD_CONTEXT) {
>> context->prio = 0;
>> if (auditd_test_task(current))
>> diff --git a/security/security.c b/security/security.c
>> index 30687e1366b7..04e160e5d4ab 100644
>> --- a/security/security.c
>> +++ b/security/security.c
>> @@ -2333,6 +2333,11 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
>> {
>> return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule);
>> }
>> +
>> +int security_audit_enable(struct task_struct *tsk)
>> +{
>> + return call_int_hook(audit_enable, 0, tsk);
>> +}
>> #endif /* CONFIG_AUDIT */
>> #ifdef CONFIG_BPF_SYSCALL
>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> index d55571c585ff..88764aa0ab43 100644
>> --- a/security/selinux/hooks.c
>> +++ b/security/selinux/hooks.c
>> @@ -6628,6 +6628,16 @@ static void selinux_ib_free_security(void *ib_sec)
>> }
>> #endif
>> +#ifdef CONFIG_AUDIT
>> +static int selinux_audit_enable(struct task_struct *tsk)
>> +{
>> + u32 sid = current_sid();
>> +
>> + return !avc_has_perm(&selinux_state, sid, sid, SECCLASS_PROCESS2,
>> + PROCESS2__AUDIT_ENABLE, NULL);
>> +}
>> +#endif
>> +
>> #ifdef CONFIG_BPF_SYSCALL
>> static int selinux_bpf(int cmd, union bpf_attr *attr,
>> unsigned int size)
>> @@ -6999,6 +7009,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
>> LSM_HOOK_INIT(audit_rule_known, selinux_audit_rule_known),
>> LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
>> LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
>> + LSM_HOOK_INIT(audit_enable, selinux_audit_enable),
>> #endif
>> #ifdef CONFIG_BPF_SYSCALL
>> diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
>> index 32e9b03be3dd..d7d856cbd486 100644
>> --- a/security/selinux/include/classmap.h
>> +++ b/security/selinux/include/classmap.h
>> @@ -52,7 +52,7 @@ struct security_class_mapping secclass_map[] = {
>> "execmem", "execstack", "execheap", "setkeycreate",
>> "setsockcreate", "getrlimit", NULL } },
>> { "process2",
>> - { "nnp_transition", "nosuid_transition", NULL } },
>> + { "nnp_transition", "nosuid_transition", "audit_enable", NULL } },
>> { "system",
>> { "ipc_info", "syslog_read", "syslog_mod",
>> "syslog_console", "module_request", "module_load", NULL } },
>>
>
More information about the Linux-security-module-archive
mailing list