Skip to content

Commit

Permalink
audit: check if queue is full after prepare_to_wait_exclusive()
Browse files Browse the repository at this point in the history
Commit 7ffb8e3 ("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: 7ffb8e3 ("audit: we don't need to __set_current_state(TASK_RUNNING)")
Signed-off-by: Eiichi Tsukata <eiichi.tsukata@nutanix.com>
  • Loading branch information
Etsukata authored and intel-lab-lkp committed May 8, 2023
1 parent 9eea11a commit cbc69d0
Showing 1 changed file with 8 additions and 2 deletions.
10 changes: 8 additions & 2 deletions kernel/audit.c
Expand Up @@ -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;
Expand Down

0 comments on commit cbc69d0

Please sign in to comment.