[PATCH v32 24/28] Audit: Add framework for auxiliary records

Casey Schaufler casey at schaufler-ca.com
Wed Mar 2 22:32:25 UTC 2022


On 2/2/2022 3:53 PM, Casey Schaufler wrote:
> Add a list for auxiliary record data to the audit_buffer structure.
> Add the audit_stamp information to the audit_buffer as there's no
> guarantee that there will be an audit_context containing the stamp
> associated with the event. At audit_log_end() time create auxiliary
> records (none are currently defined) as have been added to the list.
>
> Signed-off-by: Casey Schaufler <casey at schaufler-ca.com>

I'm really hoping for either Acks or feedback on this approach.

> ---
>   kernel/audit.c | 84 ++++++++++++++++++++++++++++++++++++++++++++------
>   1 file changed, 74 insertions(+), 10 deletions(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index f012c3786264..559fb14e0380 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -191,15 +191,25 @@ static struct audit_ctl_mutex {
>    * should be at least that large. */
>   #define AUDIT_BUFSIZ 1024
>   
> +/* The audit_context_entry contains data required to create an
> + * auxiliary record.
> + */
> +struct audit_context_entry {
> +	struct list_head	list;
> +	int			type;	/* Audit record type */
> +};
> +
>   /* The audit_buffer is used when formatting an audit record.  The caller
>    * locks briefly to get the record off the freelist or to allocate the
>    * buffer, and locks briefly to send the buffer to the netlink layer or
>    * to place it on a transmit queue.  Multiple audit_buffers can be in
>    * use simultaneously. */
>   struct audit_buffer {
> -	struct sk_buff       *skb;	/* formatted skb ready to send */
> -	struct audit_context *ctx;	/* NULL or associated context */
> -	gfp_t		     gfp_mask;
> +	struct sk_buff		*skb;	/* formatted skb ready to send */
> +	struct audit_context	*ctx;	/* NULL or associated context */
> +	struct list_head	aux_records;	/* aux record data */
> +	struct audit_stamp	stamp;	/* event stamp */
> +	gfp_t			gfp_mask;
>   };
>   
>   struct audit_reply {
> @@ -1765,6 +1775,7 @@ static struct audit_buffer *audit_buffer_alloc(struct audit_context *ctx,
>   
>   	ab->ctx = ctx;
>   	ab->gfp_mask = gfp_mask;
> +	INIT_LIST_HEAD(&ab->aux_records);
>   
>   	return ab;
>   
> @@ -1825,7 +1836,6 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
>   				     int type)
>   {
>   	struct audit_buffer *ab;
> -	struct audit_stamp stamp;
>   
>   	if (audit_initialized != AUDIT_INITIALIZED)
>   		return NULL;
> @@ -1880,14 +1890,14 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
>   		return NULL;
>   	}
>   
> -	audit_get_stamp(ab->ctx, &stamp);
> +	audit_get_stamp(ab->ctx, &ab->stamp);
>   	/* cancel dummy context to enable supporting records */
>   	if (ctx)
>   		ctx->dummy = 0;
>   	audit_log_format(ab, "audit(%llu.%03lu:%u): ",
> -			 (unsigned long long)stamp.ctime.tv_sec,
> -			 stamp.ctime.tv_nsec/1000000,
> -			 stamp.serial);
> +			 (unsigned long long)ab->stamp.ctime.tv_sec,
> +			 ab->stamp.ctime.tv_nsec/1000000,
> +			 ab->stamp.serial);
>   
>   	return ab;
>   }
> @@ -2378,7 +2388,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>   }
>   
>   /**
> - * audit_log_end - end one audit record
> + * __audit_log_end - end one audit record
>    * @ab: the audit_buffer
>    *
>    * We can not do a netlink send inside an irq context because it blocks (last
> @@ -2386,7 +2396,7 @@ int audit_signal_info(int sig, struct task_struct *t)
>    * queue and a kthread is scheduled to remove them from the queue outside the
>    * irq context.  May be called in any context.
>    */
> -void audit_log_end(struct audit_buffer *ab)
> +void __audit_log_end(struct audit_buffer *ab)
>   {
>   	struct sk_buff *skb;
>   	struct nlmsghdr *nlh;
> @@ -2408,6 +2418,60 @@ void audit_log_end(struct audit_buffer *ab)
>   		wake_up_interruptible(&kauditd_wait);
>   	} else
>   		audit_log_lost("rate limit exceeded");
> +}
> +
> +/**
> + * audit_log_end - end one audit record
> + * @ab: the audit_buffer
> + *
> + * Let __audit_log_end() handle the message while the buffer housekeeping
> + * is done here.
> + * If there are other records that have been deferred for the event
> + * create them here.
> + */
> +void audit_log_end(struct audit_buffer *ab)
> +{
> +	struct audit_context_entry *entry;
> +	struct audit_context mcontext;
> +	struct audit_context *mctx;
> +	struct audit_buffer *mab;
> +	struct list_head *l;
> +	struct list_head *n;
> +
> +	if (!ab)
> +		return;
> +
> +	__audit_log_end(ab);
> +
> +	if (list_empty(&ab->aux_records)) {
> +		audit_buffer_free(ab);
> +		return;
> +	}
> +
> +	if (ab->ctx == NULL) {
> +		mcontext.stamp = ab->stamp;
> +		mctx = &mcontext;
> +	} else
> +		mctx = ab->ctx;
> +
> +	list_for_each_safe(l, n, &ab->aux_records) {
> +		entry = list_entry(l, struct audit_context_entry, list);
> +		mab = audit_log_start(mctx, ab->gfp_mask, entry->type);
> +		if (!mab) {
> +			audit_panic("alloc error in audit_log_end");
> +			continue;
> +		}
> +		switch (entry->type) {
> +		/* Don't know of any quite yet. */
> +		default:
> +			audit_panic("Unknown type in audit_log_end");
> +			break;
> +		}
> +		__audit_log_end(mab);
> +		audit_buffer_free(mab);
> +		list_del(&entry->list);
> +		kfree(entry);
> +	}
>   
>   	audit_buffer_free(ab);
>   }



More information about the Linux-security-module-archive mailing list