Re: [PATCH v24 21/25] audit: add support for non-syscall auxiliary records

From: Casey Schaufler
Date: Tue Jan 26 2021 - 21:58:42 EST


On 1/26/2021 10:42 AM, Richard Guy Briggs wrote:
> On 2021-01-26 08:41, Casey Schaufler wrote:
>> Standalone audit records have the timestamp and serial number generated
>> on the fly and as such are unique, making them standalone. This new
>> function audit_alloc_local() generates a local audit context that will
>> be used only for a standalone record and its auxiliary record(s). The
>> context is discarded immediately after the local associated records are
>> produced.
>>
>> Signed-off-by: Richard Guy Briggs <rgb@xxxxxxxxxx>
>> Signed-off-by: Casey Schaufler <casey@xxxxxxxxxxxxxxxx>
>> Cc: linux-audit@xxxxxxxxxx
>> To: Richard Guy Briggs <rgb@xxxxxxxxxx>
> This has been minorly bothering me for several revisions... Is there a
> way for the development/authorship to be accurately reflected
> if/when this patch is merged before the contid patch set?

I don't know the right way to do that because I had to pull
some of what was in the original patch out. Any way you would
like it done is fine with me.

>
>> ---
>> include/linux/audit.h | 8 ++++++++
>> kernel/audit.h | 1 +
>> kernel/auditsc.c | 33 ++++++++++++++++++++++++++++-----
>> 3 files changed, 37 insertions(+), 5 deletions(-)
>>
>> diff --git a/include/linux/audit.h b/include/linux/audit.h
>> index 418a485af114..97cd7471e572 100644
>> --- a/include/linux/audit.h
>> +++ b/include/linux/audit.h
>> @@ -289,6 +289,8 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
>> /* Public API */
>> extern int audit_alloc(struct task_struct *task);
>> extern void __audit_free(struct task_struct *task);
>> +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
>> +extern void audit_free_context(struct audit_context *context);
>> extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1,
>> unsigned long a2, unsigned long a3);
>> extern void __audit_syscall_exit(int ret_success, long ret_value);
>> @@ -552,6 +554,12 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
>> extern int audit_n_rules;
>> extern int audit_signals;
>> #else /* CONFIG_AUDITSYSCALL */
>> ++static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
>> +{
>> + return NULL;
>> +}
>> +static inline void audit_free_context(struct audit_context *context)
>> +{ }
>> static inline int audit_alloc(struct task_struct *task)
>> {
>> return 0;
>> diff --git a/kernel/audit.h b/kernel/audit.h
>> index ce41886807bb..3f2285e1c6e0 100644
>> --- a/kernel/audit.h
>> +++ b/kernel/audit.h
>> @@ -99,6 +99,7 @@ struct audit_proctitle {
>> struct audit_context {
>> int dummy; /* must be the first element */
>> int in_syscall; /* 1 if task is in a syscall */
>> + bool local; /* local context needed */
>> enum audit_state state, current_state;
>> unsigned int serial; /* serial number for record */
>> int major; /* syscall number */
>> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
>> index de2b2ecb3aea..479b3933d788 100644
>> --- a/kernel/auditsc.c
>> +++ b/kernel/auditsc.c
>> @@ -927,11 +927,13 @@ static inline void audit_free_aux(struct audit_context *context)
>> }
>> }
>>
>> -static inline struct audit_context *audit_alloc_context(enum audit_state state)
>> +static inline struct audit_context *audit_alloc_context(enum audit_state state,
>> + gfp_t gfpflags)
>> {
>> struct audit_context *context;
>>
>> - context = kzalloc(sizeof(*context), GFP_KERNEL);
>> + /* We can be called in atomic context via audit_tg() */
>> + context = kzalloc(sizeof(*context), gfpflags);
>> if (!context)
>> return NULL;
>> context->state = state;
>> @@ -967,7 +969,8 @@ int audit_alloc(struct task_struct *tsk)
>> return 0;
>> }
>>
>> - if (!(context = audit_alloc_context(state))) {
>> + context = audit_alloc_context(state, GFP_KERNEL);
>> + if (!context) {
>> kfree(key);
>> audit_log_lost("out of memory in audit_alloc");
>> return -ENOMEM;
>> @@ -979,8 +982,27 @@ int audit_alloc(struct task_struct *tsk)
>> return 0;
>> }
>>
>> -static inline void audit_free_context(struct audit_context *context)
>> +struct audit_context *audit_alloc_local(gfp_t gfpflags)
>> {
>> + struct audit_context *context = NULL;
>> +
>> + context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
>> + if (!context) {
>> + audit_log_lost("out of memory in audit_alloc_local");
>> + goto out;
>> + }
>> + context->serial = audit_serial();
>> + ktime_get_coarse_real_ts64(&context->ctime);
>> + context->local = true;
>> +out:
>> + return context;
>> +}
>> +EXPORT_SYMBOL(audit_alloc_local);
>> +
>> +void audit_free_context(struct audit_context *context)
>> +{
>> + if (!context)
>> + return;
>> audit_free_module(context);
>> audit_free_names(context);
>> unroll_tree_refs(context, NULL, 0);
>> @@ -991,6 +1013,7 @@ static inline void audit_free_context(struct audit_context *context)
>> audit_proctitle_free(context);
>> kfree(context);
>> }
>> +EXPORT_SYMBOL(audit_free_context);
>>
>> static int audit_log_pid_context(struct audit_context *context, pid_t pid,
>> kuid_t auid, kuid_t uid,
>> @@ -2214,7 +2237,7 @@ EXPORT_SYMBOL_GPL(__audit_inode_child);
>> int auditsc_get_stamp(struct audit_context *ctx,
>> struct timespec64 *t, unsigned int *serial)
>> {
>> - if (!ctx->in_syscall)
>> + if (!ctx->in_syscall && !ctx->local)
>> return 0;
>> if (!ctx->serial)
>> ctx->serial = audit_serial();
>> --
>> 2.25.4
>>
> - RGB
>
> --
> Richard Guy Briggs <rgb@xxxxxxxxxx>
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635
>