Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac4cec44 authored by David Woodhouse's avatar David Woodhouse
Browse files

AUDIT: Stop waiting for backlog after audit_panic() happens



We force a rate-limit on auditable events by making them wait for space 
on the backlog queue. However, if auditd really is AWOL then this could 
potentially bring the entire system to a halt, depending on the audit 
rules in effect.

Firstly, make sure the wait time is honoured correctly -- it's the 
maximum time the process should wait, rather than the time to wait 
_each_ time round the loop. We were getting re-woken _each_ time a 
packet was dequeued, and the timeout was being restarted each time.

Secondly, reset the wait time after audit_panic() is called. In general 
this will be reset to zero, to allow progress to be made. If the system
is configured to _actually_ panic on audit_panic() then that will 
already have happened; otherwise we know that audit records are being 
lost anyway. 

These two tunables can't be exposed via AUDIT_GET and AUDIT_SET because 
those aren't particularly well-designed. It probably should have been 
done by sysctls or sysfs anyway -- one for a later patch.

Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 7b430437
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ static int audit_rate_limit;

/* Number of outstanding audit_buffers allowed. */
static int	audit_backlog_limit = 64;
static int	audit_backlog_wait_time = 60 * HZ;
static int	audit_backlog_wait_overflow = 0;

/* The identity of the user shutting down the audit system. */
uid_t		audit_sig_uid = -1;
@@ -655,6 +657,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,
	struct timespec		t;
	unsigned int		serial;
	int reserve;
	unsigned long timeout_start = jiffies;

	if (!audit_initialized)
		return NULL;
@@ -667,8 +670,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,

	while (audit_backlog_limit
	       && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
		if (gfp_mask & __GFP_WAIT) {
			int ret = 1;
		if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time
		    && time_before(jiffies, timeout_start + audit_backlog_wait_time)) {

			/* Wait for auditd to drain the queue a little */
			DECLARE_WAITQUEUE(wait, current);
			set_current_state(TASK_INTERRUPTIBLE);
@@ -676,11 +680,10 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,

			if (audit_backlog_limit &&
			    skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
				ret = schedule_timeout(HZ * 60);
				schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies);

			__set_current_state(TASK_RUNNING);
			remove_wait_queue(&audit_backlog_wait, &wait);
			if (ret)
			continue;
		}
		if (audit_rate_check())
@@ -690,6 +693,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int gfp_mask,
			       skb_queue_len(&audit_skb_queue),
			       audit_backlog_limit);
		audit_log_lost("backlog limit exceeded");
		audit_backlog_wait_time = audit_backlog_wait_overflow;
		wake_up(&audit_backlog_wait);
		return NULL;
	}