--- v1
+++ v35
@@ -1,164 +1,146 @@
-Convert osid to be an lsm_export structure
-instead of a u32 secid. Clean out the associated
-scaffolding. Change the name to olsm to be
-descriptive.
+Replace the single skb pointer in an audit_buffer with
+a list of skb pointers. Add the audit_stamp information
+to the audit_buffer as there's no guarantee that there
+will be an audit_context containing the stamp associated
+with the event. At audit_log_end() time create auxiliary
+records (none are currently defined) as have been added
+to the list.
+Suggested-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
---
- kernel/audit.c | 4 +---
- kernel/audit.h | 4 ++--
- kernel/auditsc.c | 36 ++++++++++++------------------------
- 3 files changed, 15 insertions(+), 29 deletions(-)
+ kernel/audit.c | 62 +++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 39 insertions(+), 23 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
-index 5226e2af9498..d83d1f05c95d 100644
+index 6b6c089512f7..4d44c05053b0 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
-@@ -2073,12 +2073,10 @@ int audit_log_task_context(struct audit_buffer *ab)
- char *ctx = NULL;
- unsigned len;
- int error;
-- u32 sid;
- struct lsm_export le;
+@@ -197,8 +197,10 @@ static struct audit_ctl_mutex {
+ * to place it on a transmit queue. Multiple audit_buffers can be in
+ * use simultaneously. */
+ struct audit_buffer {
+- struct sk_buff *skb; /* formatted skb ready to send */
++ struct sk_buff *skb; /* the skb for audit_log functions */
++ struct sk_buff_head skb_list; /* formatted skbs, ready to send */
+ struct audit_context *ctx; /* NULL or associated context */
++ struct audit_stamp stamp; /* audit stamp for these records */
+ gfp_t gfp_mask;
+ };
- security_task_getsecid(current, &le);
-- lsm_export_secid(&le, &sid);
-- if (!sid)
-+ if (!lsm_export_any(&le))
- return 0;
+@@ -1765,10 +1767,13 @@ __setup("audit_backlog_limit=", audit_backlog_limit_set);
- error = security_secid_to_secctx(&le, &ctx, &len);
-diff --git a/kernel/audit.h b/kernel/audit.h
-index e2e6fa911f9c..7d2fcdf0bc94 100644
---- a/kernel/audit.h
-+++ b/kernel/audit.h
-@@ -91,7 +91,7 @@ struct audit_names {
- kuid_t uid;
- kgid_t gid;
- dev_t rdev;
-- u32 osid;
-+ struct lsm_export olsm;
- struct audit_cap_data fcap;
- unsigned int fcap_ver;
- unsigned char type; /* record type */
-@@ -165,7 +165,7 @@ struct audit_context {
- kuid_t uid;
- kgid_t gid;
- umode_t mode;
-- u32 osid;
-+ struct lsm_export olsm;
- int has_perm;
- uid_t perm_uid;
- gid_t perm_gid;
-diff --git a/kernel/auditsc.c b/kernel/auditsc.c
-index 75d181029d40..d64775f4bb1b 100644
---- a/kernel/auditsc.c
-+++ b/kernel/auditsc.c
-@@ -645,17 +645,15 @@ static int audit_filter_rules(struct task_struct *tsk,
- if (f->lsm_rule) {
- /* Find files that match */
- if (name) {
-- lsm_export_to_all(&le, name->osid);
- result = security_audit_rule_match(
-- &le,
-+ &name->olsm,
- f->type,
- f->op,
- f->lsm_rule);
- } else if (ctx) {
- list_for_each_entry(n, &ctx->names_list, list) {
-- lsm_export_to_all(&le, n->osid);
- if (security_audit_rule_match(
-- &le,
-+ &n->olsm,
- f->type,
- f->op,
- f->lsm_rule)) {
-@@ -667,8 +665,7 @@ static int audit_filter_rules(struct task_struct *tsk,
- /* Find ipc objects that match */
- if (!ctx || ctx->type != AUDIT_IPC)
- break;
-- lsm_export_to_all(&le, ctx->ipc.osid);
-- if (security_audit_rule_match(&le,
-+ if (security_audit_rule_match(&ctx->ipc.olsm,
- f->type, f->op,
- f->lsm_rule))
- ++result;
-@@ -1187,19 +1184,17 @@ static void show_special(struct audit_context *context, int *call_panic)
- context->socketcall.args[i]);
- break; }
- case AUDIT_IPC: {
-- u32 osid = context->ipc.osid;
-+ struct lsm_export *l = &context->ipc.olsm;
+ static void audit_buffer_free(struct audit_buffer *ab)
+ {
++ struct sk_buff *skb;
++
+ if (!ab)
+ return;
- audit_log_format(ab, "ouid=%u ogid=%u mode=%#ho",
- from_kuid(&init_user_ns, context->ipc.uid),
- from_kgid(&init_user_ns, context->ipc.gid),
- context->ipc.mode);
-- if (osid) {
-+ if (lsm_export_any(l)) {
- char *ctx = NULL;
- u32 len;
-- struct lsm_export le;
-- lsm_export_to_all(&le, osid);
-- if (security_secid_to_secctx(&le, &ctx, &len)) {
-- audit_log_format(ab, " osid=%u", osid);
-+ if (security_secid_to_secctx(l, &ctx, &len)) {
-+ audit_log_format(ab, " osid=(unknown)");
- *call_panic = 1;
- } else {
- audit_log_format(ab, " obj=%s", ctx);
-@@ -1346,14 +1341,12 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
- from_kgid(&init_user_ns, n->gid),
- MAJOR(n->rdev),
- MINOR(n->rdev));
-- if (n->osid != 0) {
-+ if (lsm_export_any(&n->olsm)) {
- char *ctx = NULL;
- u32 len;
-- struct lsm_export le;
-
-- lsm_export_to_all(&le, n->osid);
-- if (security_secid_to_secctx(&le, &ctx, &len)) {
-- audit_log_format(ab, " osid=%u", n->osid);
-+ if (security_secid_to_secctx(&n->olsm, &ctx, &len)) {
-+ audit_log_format(ab, " osid=(unknown)");
- if (call_panic)
- *call_panic = 2;
- } else {
-@@ -1907,16 +1900,13 @@ static inline int audit_copy_fcaps(struct audit_names *name,
- void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
- struct inode *inode, unsigned int flags)
- {
-- struct lsm_export le;
--
- name->ino = inode->i_ino;
- name->dev = inode->i_sb->s_dev;
- name->mode = inode->i_mode;
- name->uid = inode->i_uid;
- name->gid = inode->i_gid;
- name->rdev = inode->i_rdev;
-- security_inode_getsecid(inode, &le);
-- lsm_export_secid(&le, &name->osid);
-+ security_inode_getsecid(inode, &name->olsm);
- if (flags & AUDIT_INODE_NOEVAL) {
- name->fcap_ver = -1;
- return;
-@@ -2266,13 +2256,11 @@ void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
- void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
- {
- struct audit_context *context = audit_context();
-- struct lsm_export le;
- context->ipc.uid = ipcp->uid;
- context->ipc.gid = ipcp->gid;
- context->ipc.mode = ipcp->mode;
- context->ipc.has_perm = 0;
-- security_ipc_getsecid(ipcp, &le);
-- lsm_export_secid(&le, &context->ipc.osid);
-+ security_ipc_getsecid(ipcp, &context->ipc.olsm);
- context->type = AUDIT_IPC;
+- kfree_skb(ab->skb);
++ while((skb = skb_dequeue(&ab->skb_list)))
++ kfree_skb(skb);
+ kmem_cache_free(audit_buffer_cache, ab);
}
+@@ -1784,8 +1789,12 @@ static struct audit_buffer *audit_buffer_alloc(struct audit_context *ctx,
+ ab->skb = nlmsg_new(AUDIT_BUFSIZ, gfp_mask);
+ if (!ab->skb)
+ goto err;
++
++ skb_queue_head_init(&ab->skb_list);
++ skb_queue_tail(&ab->skb_list, ab->skb);
++
+ if (!nlmsg_put(ab->skb, 0, 0, type, 0, 0))
+- goto err;
++ kfree_skb(ab->skb);
+
+ ab->ctx = ctx;
+ ab->gfp_mask = gfp_mask;
+@@ -1849,7 +1858,6 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
+ int type)
+ {
+ struct audit_buffer *ab;
+- struct audit_stamp stamp;
+
+ if (audit_initialized != AUDIT_INITIALIZED)
+ return NULL;
+@@ -1904,14 +1912,14 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
+ return NULL;
+ }
+
+- audit_get_stamp(ab->ctx, &stamp);
++ audit_get_stamp(ab->ctx, &ab->stamp);
+ /* cancel dummy context to enable supporting records */
+ if (ctx)
+ ctx->dummy = 0;
+ audit_log_format(ab, "audit(%llu.%03lu:%u): ",
+- (unsigned long long)stamp.ctime.tv_sec,
+- stamp.ctime.tv_nsec/1000000,
+- stamp.serial);
++ (unsigned long long)ab->stamp.ctime.tv_sec,
++ ab->stamp.ctime.tv_nsec/1000000,
++ ab->stamp.serial);
+
+ return ab;
+ }
+@@ -2402,26 +2410,14 @@ int audit_signal_info(int sig, struct task_struct *t)
+ }
+
+ /**
+- * audit_log_end - end one audit record
+- * @ab: the audit_buffer
+- *
+- * 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.
++ * __audit_log_end - enqueue one audit record
++ * @skb: the buffer to send
+ */
+-void audit_log_end(struct audit_buffer *ab)
++static void __audit_log_end(struct sk_buff *skb)
+ {
+- struct sk_buff *skb;
+ struct nlmsghdr *nlh;
+
+- if (!ab)
+- return;
+-
+ if (audit_rate_check()) {
+- skb = ab->skb;
+- ab->skb = NULL;
+-
+ /* setup the netlink header, see the comments in
+ * kauditd_send_multicast_skb() for length quirks */
+ nlh = nlmsg_hdr(skb);
+@@ -2432,6 +2428,26 @@ void audit_log_end(struct audit_buffer *ab)
+ wake_up_interruptible(&kauditd_wait);
+ } else
+ audit_log_lost("rate limit exceeded");
++}
++
++/**
++ * audit_log_end - end one audit record
++ * @ab: the audit_buffer
++ *
++ * 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.
++ */
++void audit_log_end(struct audit_buffer *ab)
++{
++ struct sk_buff *skb;
++
++ if (!ab)
++ return;
++
++ while ((skb = skb_dequeue(&ab->skb_list)))
++ __audit_log_end(skb);
+
+ audit_buffer_free(ab);
+ }
--
-2.19.1
+2.35.1