[PATCH v29 25/28] Audit: Add record for multiple task security contexts
From: Casey Schaufler <casey@schaufler-ca.com>
Date: 2021-09-24 18:22:37
Also in:
linux-security-module, lkml
Subsystem:
audit subsystem, security subsystem, the rest · Maintainers:
Paul Moore, Eric Paris, James Morris, "Serge E. Hallyn", Linus Torvalds
Create a new audit record AUDIT_MAC_TASK_CONTEXTS.
An example of the MAC_TASK_CONTEXTS (1420) record is:
type=UNKNOWN[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=?".
A 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.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
include/linux/security.h | 9 ++++++
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 64 ++++++++++++++++++++++++++++++++------
3 files changed, 65 insertions(+), 9 deletions(-)
diff --git a/include/linux/security.h b/include/linux/security.h
index 7096a60fbbfe..cd67d801e94c 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h@@ -230,6 +230,15 @@ static inline bool lsmblob_equal(struct lsmblob *bloba, struct lsmblob *blobb) extern int lsm_name_to_slot(char *name); extern const char *lsm_slot_to_name(int slot); +static inline bool lsm_multiple_contexts(void) +{ +#ifdef CONFIG_SECURITY + return lsm_slot_to_name(1) != NULL; +#else + return false; +#endif +} + /** * lsmblob_value - find the first non-zero value in an lsmblob structure. * @blob: Pointer to the data
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index daa481729e9b..6a0ac60688b1 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h@@ -139,6 +139,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 0d4aa6667125..707689605791 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c@@ -197,6 +197,9 @@ static struct audit_ctl_mutex { struct audit_context_entry { struct list_head list; int type; /* Audit record type */ + union { + struct lsmblob mac_task_context; + }; }; /* The audit_buffer is used when formatting an audit record. The caller
@@ -2139,6 +2142,21 @@ void audit_log_key(struct audit_buffer *ab, char *key) audit_log_format(ab, "(null)"); } +static int audit_add_aux_task(struct audit_buffer *ab, struct lsmblob *blob) +{ + struct audit_context_entry *ace; + + ace = kzalloc(sizeof(*ace), GFP_KERNEL); + if (!ace) + return -ENOMEM; + + INIT_LIST_HEAD(&ace->list); + ace->type = AUDIT_MAC_TASK_CONTEXTS; + ace->mac_task_context = *blob; + list_add(&ace->list, &ab->aux_records); + return 0; +} + int audit_log_task_context(struct audit_buffer *ab) { int error;
@@ -2149,16 +2167,22 @@ 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 (error) { - if (error != -EINVAL) - goto error_path; + if (!lsm_multiple_contexts()) { + error = security_secid_to_secctx(&blob, &context, + LSMBLOB_FIRST); + if (error) { + if (error != -EINVAL) + goto error_path; + return 0; + } + audit_log_format(ab, " subj=%s", context.context); + security_release_secctx(&context); return 0; } - - audit_log_format(ab, " subj=%s", context.context); - security_release_secctx(&context); - return 0; + audit_log_format(ab, " subj=?"); + error = audit_add_aux_task(ab, &blob); + if (!error) + return 0; error_path: audit_panic("error in audit_log_task_context");
@@ -2419,9 +2443,12 @@ void audit_log_end(struct audit_buffer *ab) struct audit_context_entry *entry; struct audit_context mcontext; struct audit_context *mctx; + struct lsmcontext lcontext; struct audit_buffer *mab; struct list_head *l; struct list_head *n; + int rc; + int i; if (!ab) return;
@@ -2448,7 +2475,26 @@ void audit_log_end(struct audit_buffer *ab) continue; } switch (entry->type) { - /* Don't know of any quite yet. */ + case AUDIT_MAC_TASK_CONTEXTS: + for (i = 0; i < LSMBLOB_ENTRIES; i++) { + if (entry->mac_task_context.secid[i] == 0) + continue; + rc = security_secid_to_secctx( + &entry->mac_task_context, + &lcontext, i); + if (rc) { + if (rc != -EINVAL) + audit_panic("error in audit_log_end"); + audit_log_format(mab, "subj_%s=?", + lsm_slot_to_name(0)); + } else { + audit_log_format(mab, "subj_%s=%s", + lsm_slot_to_name(0), + lcontext.context); + security_release_secctx(&lcontext); + } + } + break; default: audit_panic("Unknown type in audit_log_end"); break;
--
2.31.1