Commit 6441998e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull audit fix from Paul Moore:
 "A single patch to fix a problem where the audit queue could grow
  unbounded when the audit daemon is forcibly stopped"

* tag 'audit-pr-20211216' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: improve robustness of the audit queue handling
parents 180f3bcf f4b3ee3c
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -718,7 +718,7 @@ static int kauditd_send_queue(struct sock *sk, u32 portid,
{
	int rc = 0;
	struct sk_buff *skb;
	static unsigned int failed = 0;
	unsigned int failed = 0;

	/* NOTE: kauditd_thread takes care of all our locking, we just use
	 *       the netlink info passed to us (e.g. sk and portid) */
@@ -735,32 +735,30 @@ static int kauditd_send_queue(struct sock *sk, u32 portid,
			continue;
		}

retry:
		/* grab an extra skb reference in case of error */
		skb_get(skb);
		rc = netlink_unicast(sk, skb, portid, 0);
		if (rc < 0) {
			/* fatal failure for our queue flush attempt? */
			/* send failed - try a few times unless fatal error */
			if (++failed >= retry_limit ||
			    rc == -ECONNREFUSED || rc == -EPERM) {
				/* yes - error processing for the queue */
				sk = NULL;
				if (err_hook)
					(*err_hook)(skb);
				if (!skb_hook)
					goto out;
				/* keep processing with the skb_hook */
				if (rc == -EAGAIN)
					rc = 0;
				/* continue to drain the queue */
				continue;
			} else
				/* no - requeue to preserve ordering */
				skb_queue_head(queue, skb);
				goto retry;
		} else {
			/* it worked - drop the extra reference and continue */
			/* skb sent - drop the extra reference and continue */
			consume_skb(skb);
			failed = 0;
		}
	}

out:
	return (rc >= 0 ? 0 : rc);
}

@@ -1609,7 +1607,8 @@ static int __net_init audit_net_init(struct net *net)
		audit_panic("cannot initialize netlink socket in namespace");
		return -ENOMEM;
	}
	aunet->sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
	/* limit the timeout in case auditd is blocked/stopped */
	aunet->sk->sk_sndtimeo = HZ / 10;

	return 0;
}