[prev in list] [next in list] [prev in thread] [next in thread]
List: oss-security
Subject: Re: [oss-security] CVE-2020-10708 kernel: race condition in kernel/audit.c may allow low privilege u
From: Steve Grubb <sgrubb () redhat ! com>
Date: 2020-04-17 13:24:42
Message-ID: 7526463.NqbLCg6IT0 () x2
[Download RAW message or body]
On Friday, April 17, 2020 12:40:10 AM EDT 陈伟宸(田各) wrote:
> "A race condition was found in the Linux kernel audit subsystem. When the
> system is configured to panic on events being dropped, an attacker who is
> able to trigger an audit event that starts while auditd is in the process
> of starting may be able to cause the system to panic by exploiting a race
> condition in audit event handling. This creates a denial of service by
> causing a panic."
While this is theoretically possible, starting the audit daemon requires
privileges. As root, you can do many worse things. Or just call panic
yourself. In practice, there isn't really a problem because the audit daemon
starts, registers the pid, then the rules get loaded. So, I'd say yes there
is a race that should get fixed. But you're shooting yourself in the foot for
looping on restarting the audit daemon as root.
Also, there is a configuration option, --backlog_wait_time, which also has
something to do with whether or not panic will get called.
-Steve
> https://bugzilla.redhat.com/show_bug.cgi?id=1822593
>
> Env:
> Red Hat Enterprise Linux Server release 7.7 (Maipo)
> 3.10.0-1062.12.1.el7.x86_64
>
> Details:
> Function audit_log_end and audit_panic may have race conditions when auditd
> is restarting because audit_pid can be NULL in audit_log_end and then
> become not NULL in audit_panic, which may allow attackers to trigger
> kernel panic. Here is panic call stack:
>
>
> void audit_log_end(struct audit_buffer *ab)
> {
> if (!ab)
> return;
> if (!audit_rate_check()) {
> audit_log_lost("rate limit exceeded");
> } else {
> struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
> nlh->nlmsg_len = ab->skb->len - NLMSG_HDRLEN;
>
> if (audit_pid) {
> skb_queue_tail(&audit_skb_queue, ab->skb);
> wake_up_interruptible(&kauditd_wait);
> } else {
> audit_printk_skb(ab->skb); // <- audit_pid == NULL when auditd
> is killed }
> ab->skb = NULL;
> }
> audit_buffer_free(ab);
> }
> -> audit_printk_skb -> audit_log_lost ->
> void audit_panic(const char *message)
> {
> switch (audit_failure)
> {
> case AUDIT_FAIL_SILENT:
> break;
> case AUDIT_FAIL_PRINTK:
> if (printk_ratelimit())
> printk(KERN_ERR "audit: %s\n", message);
> break;
> case AUDIT_FAIL_PANIC:
> /* test audit_pid since printk is always losey, why bother? */
> if (audit_pid) // <- audit_pid not NULL because auditd is
> restarting panic("audit: %s\n", message);
> break;
> }
> }
>
> How to reproduce:
> 1. set audit-failure to AUDIT_FAIL_PANIC(2) and add a random audit rule
> like: [root@test ~]# cat /etc/audit/rules.d/audit.rules
> -D
> -b 8192
> -f 2
> -w /etc/hosts -p rwa -k hosts
> 2. keep killing auditd and then starting auditd, for example:
> while true; do ps aux | grep "/sbin/auditd" | grep -v "grep" | awk '{print
> $2}' | xargs kill; service auditd start; systemctl reset-failed
> auditd.service; done 3. log in a low privilege user and keep reading
> /etc/hosts, for example: while true; do cat /etc/hosts > /dev/null; done
> 4. kernel panic will happen within several minutes
>
> Thanks.
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic