Rather then reading from userspace on every call, cache the page in the audit_context and couple to that objects life-cycle.
Change-Id: Ia0d432bc4aba8588840f0dc0026a1e9483e5b485 Signed-off-by: William Roberts <wrobe...@tresys.com> --- kernel/auditsc.c | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 45fd3d0..27f8224 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -270,6 +270,7 @@ struct audit_context { } mmap; }; int fds[2]; + char *cmdline; #if AUDIT_DEBUG int put_count; @@ -1044,6 +1045,14 @@ static inline void audit_free_aux(struct audit_context *context) } } +static inline void audit_cmdline_free(struct audit_context *ctx) +{ + if (!ctx->cmdline) + return; + free_page((unsigned long)ctx->cmdline); + ctx->cmdline = NULL; +} + static inline void audit_zero_context(struct audit_context *context, enum audit_state state) { @@ -1118,6 +1127,7 @@ static inline void audit_free_context(struct audit_context *context) audit_free_aux(context); kfree(context->filterkey); kfree(context->sockaddr); + audit_cmdline_free(context); kfree(context); context = previous; } while (context); @@ -1154,35 +1164,51 @@ error_path: EXPORT_SYMBOL(audit_log_task_context); -static void audit_log_add_cmdline(struct audit_buffer *ab, +static char *audit_cmdline_get_page(struct audit_buffer *ab, struct task_struct *tsk) { int len; unsigned long page; - char *msg = "(null)"; - - audit_log_format(ab, " cmdline="); /* Get the process cmdline */ page = __get_free_page(GFP_TEMPORARY); if (!page) { - audit_log_untrustedstring(ab, msg); - return; + return NULL; } len = proc_pid_cmdline(tsk, (char *)page); if (len <= 0) { free_page(page); - audit_log_untrustedstring(ab, msg); - return; + return NULL; } /* * Ensure NULL terminated! Application could * could be using setproctitle(3). */ ((char *)page)[len-1] = '\0'; - msg = (char *)page; + + /* XXX: Re-alloc to something smaller then a page here? */ + return (char *)page; +} + +static void audit_log_cmdline(struct audit_buffer *ab, struct task_struct *tsk, + struct audit_context *context) +{ + char *msg = "(null)"; + + audit_log_format(ab, " cmdline="); + + /* Already cached */ + if (context->cmdline) { + msg = context->cmdline; + goto out; + } + /* Not cached yet */ + context->cmdline = audit_cmdline_get_page(ab, tsk); + if (!context->cmdline) + goto out; + msg = context->cmdline; +out: audit_log_untrustedstring(ab, msg); - free_page(page); } static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) @@ -1211,7 +1237,6 @@ static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk } up_read(&mm->mmap_sem); } - audit_log_add_cmdline(ab, tsk); audit_log_task_context(ab); } @@ -1679,6 +1704,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts audit_log_task_info(ab, tsk); + audit_log_cmdline(ab, tsk, context); audit_log_key(ab, context->filterkey); audit_log_end(ab); -- 1.7.9.5 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit