audit: convert PPIDs to the inital PID namespace.
[firefly-linux-kernel-4.4.55.git] / kernel / auditsc.c
index 6874c1fd453d2f90d49ece57c6a1357b16212fda..a6cf7ab56e61ebbe340328b575792c84f9fc8f65 100644 (file)
@@ -70,6 +70,7 @@
 #include <linux/capability.h>
 #include <linux/fs_struct.h>
 #include <linux/compat.h>
+#include <linux/ctype.h>
 
 #include "audit.h"
 
@@ -81,6 +82,9 @@
 /* no execve audit message should be longer than this (userspace limits) */
 #define MAX_EXECVE_AUDIT_LEN 7500
 
+/* max length to print of cmdline/proctitle value during audit */
+#define MAX_PROCTITLE_AUDIT_LEN 128
+
 /* number of audit rules */
 int audit_n_rules;
 
@@ -461,7 +465,7 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_PPID:
                        if (ctx) {
                                if (!ctx->ppid)
-                                       ctx->ppid = sys_getppid();
+                                       ctx->ppid = task_ppid_nr(tsk);
                                result = audit_comparator(ctx->ppid, f->op, f->val);
                        }
                        break;
@@ -807,7 +811,8 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx)
        rcu_read_unlock();
 }
 
-static inline struct audit_context *audit_get_context(struct task_struct *tsk,
+/* Transfer the audit context pointer to the caller, clearing it in the tsk's struct */
+static inline struct audit_context *audit_take_context(struct task_struct *tsk,
                                                      int return_valid,
                                                      long return_code)
 {
@@ -844,6 +849,13 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk,
        return context;
 }
 
+static inline void audit_proctitle_free(struct audit_context *context)
+{
+       kfree(context->proctitle.value);
+       context->proctitle.value = NULL;
+       context->proctitle.len = 0;
+}
+
 static inline void audit_free_names(struct audit_context *context)
 {
        struct audit_names *n, *next;
@@ -956,6 +968,7 @@ static inline void audit_free_context(struct audit_context *context)
        audit_free_aux(context);
        kfree(context->filterkey);
        kfree(context->sockaddr);
+       audit_proctitle_free(context);
        kfree(context);
 }
 
@@ -1272,6 +1285,59 @@ static void show_special(struct audit_context *context, int *call_panic)
        audit_log_end(ab);
 }
 
+static inline int audit_proctitle_rtrim(char *proctitle, int len)
+{
+       char *end = proctitle + len - 1;
+       while (end > proctitle && !isprint(*end))
+               end--;
+
+       /* catch the case where proctitle is only 1 non-print character */
+       len = end - proctitle + 1;
+       len -= isprint(proctitle[len-1]) == 0;
+       return len;
+}
+
+static void audit_log_proctitle(struct task_struct *tsk,
+                        struct audit_context *context)
+{
+       int res;
+       char *buf;
+       char *msg = "(null)";
+       int len = strlen(msg);
+       struct audit_buffer *ab;
+
+       ab = audit_log_start(context, GFP_KERNEL, AUDIT_PROCTITLE);
+       if (!ab)
+               return; /* audit_panic or being filtered */
+
+       audit_log_format(ab, "proctitle=");
+
+       /* Not  cached */
+       if (!context->proctitle.value) {
+               buf = kmalloc(MAX_PROCTITLE_AUDIT_LEN, GFP_KERNEL);
+               if (!buf)
+                       goto out;
+               /* Historically called this from procfs naming */
+               res = get_cmdline(tsk, buf, MAX_PROCTITLE_AUDIT_LEN);
+               if (res == 0) {
+                       kfree(buf);
+                       goto out;
+               }
+               res = audit_proctitle_rtrim(buf, res);
+               if (res == 0) {
+                       kfree(buf);
+                       goto out;
+               }
+               context->proctitle.value = buf;
+               context->proctitle.len = res;
+       }
+       msg = context->proctitle.value;
+       len = context->proctitle.len;
+out:
+       audit_log_n_untrustedstring(ab, msg, len);
+       audit_log_end(ab);
+}
+
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
 {
        int i, call_panic = 0;
@@ -1389,6 +1455,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                audit_log_name(context, n, NULL, i++, &call_panic);
        }
 
+       audit_log_proctitle(tsk, context);
+
        /* Send end of event record to help user space know we are finished */
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);
        if (ab)
@@ -1407,7 +1475,7 @@ void __audit_free(struct task_struct *tsk)
 {
        struct audit_context *context;
 
-       context = audit_get_context(tsk, 0, 0);
+       context = audit_take_context(tsk, 0, 0);
        if (!context)
                return;
 
@@ -1501,7 +1569,7 @@ void __audit_syscall_exit(int success, long return_code)
        else
                success = AUDITSC_FAILURE;
 
-       context = audit_get_context(tsk, success, return_code);
+       context = audit_take_context(tsk, success, return_code);
        if (!context)
                return;