Merge tag 'audit-pr-20220110' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
[linux-2.6-microblaze.git] / kernel / audit.c
index 79c1461..e4bbe2c 100644 (file)
@@ -1444,7 +1444,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        if (err)
                                return err;
                }
-               sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+               sig_data = kmalloc(struct_size(sig_data, ctx, len), GFP_KERNEL);
                if (!sig_data) {
                        if (audit_sig_sid)
                                security_release_secctx(ctx, len);
@@ -1457,7 +1457,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        security_release_secctx(ctx, len);
                }
                audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
-                                sig_data, sizeof(*sig_data) + len);
+                                sig_data, struct_size(sig_data, ctx, len));
                kfree(sig_data);
                break;
        case AUDIT_TTY_GET: {
@@ -1540,6 +1540,20 @@ static void audit_receive(struct sk_buff  *skb)
                nlh = nlmsg_next(nlh, &len);
        }
        audit_ctl_unlock();
+
+       /* can't block with the ctrl lock, so penalize the sender now */
+       if (audit_backlog_limit &&
+           (skb_queue_len(&audit_queue) > audit_backlog_limit)) {
+               DECLARE_WAITQUEUE(wait, current);
+
+               /* wake kauditd to try and flush the queue */
+               wake_up_interruptible(&kauditd_wait);
+
+               add_wait_queue_exclusive(&audit_backlog_wait, &wait);
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(audit_backlog_wait_time);
+               remove_wait_queue(&audit_backlog_wait, &wait);
+       }
 }
 
 /* Log information about who is connecting to the audit multicast socket */
@@ -1824,7 +1838,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
         *    task_tgid_vnr() since auditd_pid is set in audit_receive_msg()
         *    using a PID anchored in the caller's namespace
         * 2. generator holding the audit_cmd_mutex - we don't want to block
-        *    while holding the mutex */
+        *    while holding the mutex, although we do penalize the sender
+        *    later in audit_receive() when it is safe to block
+        */
        if (!(auditd_test_task(current) || audit_ctl_owner_current())) {
                long stime = audit_backlog_wait_time;