diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-07-10 19:03:37 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-07-10 19:03:37 -0700 |
| commit | bf124bae08c35cb8b5392ec8005f9890833b9056 (patch) | |
| tree | fd4eaffef5c5821ba8c31a00e4f7df043b8c798b /kernel | |
| parent | ccce5f6e7c86f103d76534e2d06d1c903dce551c (diff) | |
| parent | 65dfde57d1e29ce2b76fc23dd565eccd5c0bc0f0 (diff) | |
Merge tag 'audit-pr-20260710' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit
Pull audit fixes from Paul Moore:
"Two relatively small audit patches to fix potential data races with
the main audit backlog queue as well as possible integer overflows
when logging data as hex strings"
* tag 'audit-pr-20260710' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
audit: fix potential integer overflow in audit_log_n_hex()
audit: Fix data races of skb_queue_len() readers on audit_queue
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index dcc657d35776..562476937fa7 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -62,6 +62,7 @@ #include <net/ip.h> #include <net/ipv6.h> #include <linux/sctp.h> +#include <linux/overflow.h> #include "audit.h" @@ -950,7 +951,7 @@ main_queue: * do the multicast send and rotate records from the * main queue to the retry/hold queues */ wait_event_freezable(kauditd_wait, - (skb_queue_len(&audit_queue) ? 1 : 0)); + (skb_queue_len_lockless(&audit_queue) ? 1 : 0)); } return 0; @@ -1283,7 +1284,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh, s.rate_limit = audit_rate_limit; s.backlog_limit = audit_backlog_limit; s.lost = atomic_read(&audit_lost); - s.backlog = skb_queue_len(&audit_queue); + s.backlog = skb_queue_len_lockless(&audit_queue); s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL; s.backlog_wait_time = audit_backlog_wait_time; s.backlog_wait_time_actual = atomic_read(&audit_backlog_wait_time_actual); @@ -1627,7 +1628,7 @@ static void audit_receive(struct sk_buff *skb) /* can't block with the ctrl lock, so penalize the sender now */ if (audit_backlog_limit && - (skb_queue_len(&audit_queue) > audit_backlog_limit)) { + (skb_queue_len_lockless(&audit_queue) > audit_backlog_limit)) { DECLARE_WAITQUEUE(wait, current); /* wake kauditd to try and flush the queue */ @@ -1933,7 +1934,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, long stime = audit_backlog_wait_time; while (audit_backlog_limit && - (skb_queue_len(&audit_queue) > audit_backlog_limit)) { + (skb_queue_len_lockless(&audit_queue) > audit_backlog_limit)) { /* wake kauditd to try and flush the queue */ wake_up_interruptible(&kauditd_wait); @@ -1953,7 +1954,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, } else { if (audit_rate_check() && printk_ratelimit()) pr_warn("audit_backlog=%d > audit_backlog_limit=%d\n", - skb_queue_len(&audit_queue), + skb_queue_len_lockless(&audit_queue), audit_backlog_limit); audit_log_lost("backlog limit exceeded"); return NULL; @@ -2080,7 +2081,8 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len) { - int i, avail, new_len; + int avail; + size_t i, new_len; unsigned char *ptr; struct sk_buff *skb; @@ -2090,7 +2092,12 @@ void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, BUG_ON(!ab->skb); skb = ab->skb; avail = skb_tailroom(skb); - new_len = len<<1; + + if (check_shl_overflow(len, 1, &new_len)) { + audit_log_format(ab, "?"); + return; + } + if (new_len >= avail) { /* Round the buffer request up to the next multiple */ new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1); |
