Create a new audit record AUDIT_MAC_TASK_CONTEXTS.
An example of the MAC_TASK_CONTEXTS (1420) record is:

    type=MAC_TASK_CONTEXTS[1420]
    msg=audit(1600880931.832:113)
    subj_apparmor=unconfined
    subj_smack=_

When an audit event includes a AUDIT_MAC_TASK_CONTEXTS record
the "subj=" field in other records in the event will be "subj=?".
An AUDIT_MAC_TASK_CONTEXTS record is supplied when the system has
multiple security modules that may make access decisions based
on a subject security context.

Functions are created to manage the skb list in the audit_buffer.

Signed-off-by: Casey Schaufler <[email protected]>
---
 include/uapi/linux/audit.h |   1 +
 kernel/audit.c             | 104 ++++++++++++++++++++++++++++++++-----
 2 files changed, 93 insertions(+), 12 deletions(-)

diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 8eda133ca4c1..af0aaccfaf57 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -143,6 +143,7 @@
 #define AUDIT_MAC_UNLBL_STCDEL 1417    /* NetLabel: del a static label */
 #define AUDIT_MAC_CALIPSO_ADD  1418    /* NetLabel: add CALIPSO DOI entry */
 #define AUDIT_MAC_CALIPSO_DEL  1419    /* NetLabel: del CALIPSO DOI entry */
+#define AUDIT_MAC_TASK_CONTEXTS        1420    /* Multiple LSM task contexts */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
diff --git a/kernel/audit.c b/kernel/audit.c
index 4713e66a12af..ad825af203cf 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2147,8 +2147,65 @@ void audit_log_key(struct audit_buffer *ab, char *key)
                audit_log_format(ab, "(null)");
 }
 
+/*
+ * A brief note on aux record management.
+ *
+ * Aux records are allocated and added to the skb list of
+ * the "main" record. The ab->skb is reset to point to the
+ * aux record on its creation. When the aux record in complete
+ * ab->skb has to be reset to point to the "main" record.
+ * This allows the audit_log_ functions to be ignorant of
+ * which kind of record it is logging to. It also avoids adding
+ * special data for aux records.
+ */
+
+/**
+ * audit_buffer_aux_new - Add an aux record buffer to the skb list
+ * @ab: audit_buffer
+ * @type: message type
+ *
+ * On success ab->skb will point to the new aux record.
+ * Returns 0 on success, -ENOMEM should allocation fail.
+ */
+static int audit_buffer_aux_new(struct audit_buffer *ab, int type)
+{
+       WARN_ON(ab->skb != skb_peek(&ab->skb_list));
+
+       ab->skb = nlmsg_new(AUDIT_BUFSIZ, ab->gfp_mask);
+       if (!ab->skb)
+               goto err;
+       if (!nlmsg_put(ab->skb, 0, 0, type, 0, 0))
+               goto err;
+       skb_queue_tail(&ab->skb_list, ab->skb);
+
+       audit_log_format(ab, "audit(%llu.%03lu:%u): ",
+                        (unsigned long long)ab->stamp.ctime.tv_sec,
+                        ab->stamp.ctime.tv_nsec/1000000,
+                        ab->stamp.serial);
+
+       return 0;
+
+err:
+       kfree_skb(ab->skb);
+       ab->skb = skb_peek(&ab->skb_list);
+       return -ENOMEM;
+}
+
+/**
+ * audit_buffer_aux_end - Switch back to the "main" record from an aux record
+ * @ab: audit_buffer
+ *
+ * Restores the "main" audit record to ab->skb.
+ */
+static void audit_buffer_aux_end(struct audit_buffer *ab)
+{
+       ab->skb = skb_peek(&ab->skb_list);
+}
+
+
 int audit_log_task_context(struct audit_buffer *ab)
 {
+       int i;
        int error;
        struct lsmblob blob;
        struct lsmcontext context;
@@ -2157,16 +2214,44 @@ int audit_log_task_context(struct audit_buffer *ab)
        if (!lsmblob_is_set(&blob))
                return 0;
 
-       error = security_secid_to_secctx(&blob, &context, LSMBLOB_FIRST);
+       if (!lsm_multiple_contexts()) {
+               error = security_secid_to_secctx(&blob, &context,
+                                                LSMBLOB_FIRST);
+               if (error) {
+                       if (error != -EINVAL)
+                               goto error_path;
+                       return 0;
+               }
 
-       if (error) {
-               if (error != -EINVAL)
+               audit_log_format(ab, " subj=%s", context.context);
+               security_release_secctx(&context);
+       } else {
+               /* Multiple LSMs provide contexts. Include an aux record. */
+               audit_log_format(ab, " subj=?");
+               error = audit_buffer_aux_new(ab, AUDIT_MAC_TASK_CONTEXTS);
+               if (error)
                        goto error_path;
-               return 0;
+               for (i = 0; i < LSMBLOB_ENTRIES; i++) {
+                       if (blob.secid[i] == 0)
+                               continue;
+                       error = security_secid_to_secctx(&blob, &context, i);
+                       if (error) {
+                               if (error != -EINVAL)
+                                       audit_panic("error in 
audit_log_task_context");
+                               audit_log_format(ab, "%ssubj_%s=?",
+                                                i ? " " : "",
+                                                lsm_slot_to_name(i));
+                       } else {
+                               audit_log_format(ab, "%ssubj_%s=%s",
+                                                i ? " " : "",
+                                                lsm_slot_to_name(i),
+                                                context.context);
+                               security_release_secctx(&context);
+                       }
+               }
+               audit_buffer_aux_end(ab);
        }
 
-       audit_log_format(ab, " subj=%s", context.context);
-       security_release_secctx(&context);
        return 0;
 
 error_path:
@@ -2382,13 +2467,8 @@ int audit_signal_info(int sig, struct task_struct *t)
 }
 
 /**
- * __audit_log_end - end one audit record
+ * __audit_log_end - send one audit record
  * @skb: the buffer to send
- *
- * We can not do a netlink send inside an irq context because it blocks (last
- * arg, flags, is not set to MSG_DONTWAIT), so the audit buffer is placed on a
- * queue and a kthread is scheduled to remove them from the queue outside the
- * irq context.  May be called in any context.
  */
 static void __audit_log_end(struct sk_buff *skb)
 {
-- 
2.31.1

--
Linux-audit mailing list
[email protected]
https://listman.redhat.com/mailman/listinfo/linux-audit

Reply via email to