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

Reply via email to