[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