From mboxrd@z Thu Jan 1 00:00:00 1970 From: Steve Grubb Subject: Re: [PATCH 1/2] Audit: break up execve arguments into multiple records Date: Wed, 3 Oct 2007 13:27:07 -0400 Message-ID: <200710031327.08736.sgrubb@redhat.com> References: <1191360334.9506.28.camel@localhost.localdomain> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1191360334.9506.28.camel@localhost.localdomain> Content-Disposition: inline List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-audit-bounces@redhat.com Errors-To: linux-audit-bounces@redhat.com To: Eric Paris Cc: linux-audit@redhat.com List-Id: linux-audit@redhat.com 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 Acked-by: Steve Grubb > --- > 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: {