summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-07-10 19:03:37 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-07-10 19:03:37 -0700
commitbf124bae08c35cb8b5392ec8005f9890833b9056 (patch)
treefd4eaffef5c5821ba8c31a00e4f7df043b8c798b /kernel
parentccce5f6e7c86f103d76534e2d06d1c903dce551c (diff)
parent65dfde57d1e29ce2b76fc23dd565eccd5c0bc0f0 (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.c21
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);