From cbc69d0c34bdbc06ebca3e3020cfc24034fcf173 Mon Sep 17 00:00:00 2001 From: Eiichi Tsukata Date: Mon, 8 May 2023 07:58:12 +0000 Subject: [PATCH] audit: check if queue is full after prepare_to_wait_exclusive() Commit 7ffb8e317bae ("audit: we don't need to __set_current_state(TASK_RUNNING)") accidentally moved queue full check before add_wait_queue_exclusive() which introduced the following race: CPU1 CPU2 ======== ======== (in audit_log_start()) (in kauditd_thread()) queue is full wake_up(&audit_backlog_wait) wait_event_freezable() add_wait_queue_exclusive() ... schedule_timeout() Once this happens, both audit_log_start() and kauditd_thread() can cause deadlock for up to backlog_wait_time waiting for each other. To prevent the race, this patch adds queue full check after prepare_to_wait_exclusive(). Fixes: 7ffb8e317bae ("audit: we don't need to __set_current_state(TASK_RUNNING)") Signed-off-by: Eiichi Tsukata --- kernel/audit.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index bcbb0ba33c842e..d37a3a045230d8 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -644,8 +644,14 @@ static long wait_for_kauditd(long stime) prepare_to_wait_exclusive(&audit_backlog_wait, &wait, TASK_UNINTERRUPTIBLE); - rtime = schedule_timeout(stime); - atomic_add(stime - rtime, &audit_backlog_wait_time_actual); + + /* need to check if the queue is full again because kauditd might have + * flushed the queue and went to sleep after prepare_to_wait_exclusive() + */ + if (audit_queue_full(&audit_queue)) { + rtime = schedule_timeout(stime); + atomic_add(stime - rtime, &audit_backlog_wait_time_actual); + } finish_wait(&audit_backlog_wait, &wait); return rtime;