[PATCH 1/2] Audit: break up execve arguments into multiple records

Steve Grubb sgrubb at redhat.com
Wed Oct 3 17:27:07 UTC 2007


On Tuesday 02 October 2007 17:25:34 Eric Paris wrote:
> Break the auditing of execve arguments into smaller records if there are
> a lot.  Currently the limit is 32k if audit is on (intended to fit in a
> single netlink message) but userspace actually has trouble a little over
> 8k.  This patch takes long argument lists and just emits them in
> sequential records.  We log all of them and userspace is happy!  It also
> means we don't need as much kernel memory to hold the buffer while we
> build that one huge record.
>
> Signed-off-by: Eric Paris <eparis at redhat.com>

Acked-by: Steve Grubb <sgrubb at redhat.com>

> ---
>  kernel/auditsc.c |   39 +++++++++++++++++++++++++++++++++------
>  1 files changed, 33 insertions(+), 6 deletions(-)
>
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 04f3ffb..f9f61db 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -819,11 +819,12 @@ static int audit_log_pid_context(struct audit_context
> *context, pid_t pid, return rc;
>  }
>
> -static void audit_log_execve_info(struct audit_buffer *ab,
> +static void audit_log_execve_info(struct audit_context *context,
> +		struct audit_buffer **ab,
>  		struct audit_aux_data_execve *axi)
>  {
>  	int i;
> -	long len, ret;
> +	long len, ret, len_sent = 0;
>  	const char __user *p;
>  	char *buf;
>
> @@ -833,7 +834,11 @@ static void audit_log_execve_info(struct audit_buffer
> *ab, p = (const char __user *)axi->mm->arg_start;
>
>  	for (i = 0; i < axi->argc; i++, p += len) {
> +		char tmp_buf[12];
> +		/* how many digits are in i? */
> +		int i_len = snprintf(tmp_buf, 12, "%d", i);
> +
>  		len = strnlen_user(p, MAX_ARG_STRLEN);
>  		/*
>  		 * We just created this mm, if we can't find the strings
>  		 * we just copied into it something is _very_ wrong. Similar
> @@ -862,9 +867,31 @@ static void audit_log_execve_info(struct audit_buffer
> *ab, send_sig(SIGKILL, current, 0);
>  		}
>
> -		audit_log_format(ab, "a%d=", i);
> -		audit_log_untrustedstring(ab, buf);
> -		audit_log_format(ab, "\n");
> +		/*
> +		 * If there are a lot of args just break them into multiple
> +		 * messages.  the last ab started will get closed by the
> +		 * caller.
> +		 *
> +		 * 7500 bytes just seemed like an arbitrily large enough
> +		 * number to minimize message and keep allocations in
> +		 * in audit_expand nice and small. (some audit userspace
> +		 * can't handle messages > ~8k)
> +		 *
> +		 * add +3 because we know at least a = and \n will be sent
> +		 * as well as the number of digits in i (i_len).
> +		 */
> +		len_sent += (len + 3 + i_len);
> +		if (len_sent > 7500) {
> +			len_sent = len + 3 + i_len;
> +			audit_log_end(*ab);
> +			*ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);
> +			if (!*ab)
> +				return;
> +		}
> +
> +		audit_log_format(*ab, "a%d=", i);
> +		audit_log_untrustedstring(*ab, buf);
> +		audit_log_format(*ab, "\n");
>
>  		kfree(buf);
>  	}
> @@ -1010,7 +1037,7 @@ static void audit_log_exit(struct audit_context
> *context, struct task_struct *ts
>
>  		case AUDIT_EXECVE: {
>  			struct audit_aux_data_execve *axi = (void *)aux;
> -			audit_log_execve_info(ab, axi);
> +			audit_log_execve_info(context, &ab, axi);
>  			break; }
>
>  		case AUDIT_SOCKETCALL: {





More information about the Linux-audit mailing list