Skip to content

Commit 7a7082b

Browse files
committed
audit: Send netlink ACK before setting connection in auditd_set
jira LE-3201 Rebuild_History Non-Buildable kernel-rt-4.18.0-553.30.1.rt7.371.el8_10 commit-author Chris Riches <[email protected]> commit 022732e When auditd_set sets the auditd_conn pointer, audit messages can immediately be put on the socket by other kernel threads. If the backlog is large or the rate is high, this can immediately fill the socket buffer. If the audit daemon requested an ACK for this operation, a full socket buffer causes the ACK to get dropped, also setting ENOBUFS on the socket. To avoid this race and ensure ACKs get through, fast-track the ACK in this specific case to ensure it is sent before auditd_conn is set. Signed-off-by: Chris Riches <[email protected]> [PM: fix some tab vs space damage] Signed-off-by: Paul Moore <[email protected]> (cherry picked from commit 022732e) Signed-off-by: Jonathan Maple <[email protected]>
1 parent 8a15861 commit 7a7082b

File tree

1 file changed

+24
-7
lines changed

1 file changed

+24
-7
lines changed

kernel/audit.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -503,15 +503,19 @@ static void auditd_conn_free(struct rcu_head *rcu)
503503
* @pid: auditd PID
504504
* @portid: auditd netlink portid
505505
* @net: auditd network namespace pointer
506+
* @skb: the netlink command from the audit daemon
507+
* @ack: netlink ack flag, cleared if ack'd here
506508
*
507509
* Description:
508510
* This function will obtain and drop network namespace references as
509511
* necessary. Returns zero on success, negative values on failure.
510512
*/
511-
static int auditd_set(struct pid *pid, u32 portid, struct net *net)
513+
static int auditd_set(struct pid *pid, u32 portid, struct net *net,
514+
struct sk_buff *skb, bool *ack)
512515
{
513516
unsigned long flags;
514517
struct auditd_connection *ac_old, *ac_new;
518+
struct nlmsghdr *nlh;
515519

516520
if (!pid || !net)
517521
return -EINVAL;
@@ -523,6 +527,13 @@ static int auditd_set(struct pid *pid, u32 portid, struct net *net)
523527
ac_new->portid = portid;
524528
ac_new->net = get_net(net);
525529

530+
/* send the ack now to avoid a race with the queue backlog */
531+
if (*ack) {
532+
nlh = nlmsg_hdr(skb);
533+
netlink_ack(skb, nlh, 0, NULL);
534+
*ack = false;
535+
}
536+
526537
spin_lock_irqsave(&auditd_conn_lock, flags);
527538
ac_old = rcu_dereference_protected(auditd_conn,
528539
lockdep_is_held(&auditd_conn_lock));
@@ -1216,7 +1227,8 @@ static int audit_replace(struct pid *pid)
12161227
return auditd_send_unicast_skb(skb);
12171228
}
12181229

1219-
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1230+
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
1231+
bool *ack)
12201232
{
12211233
u32 seq;
12221234
void *data;
@@ -1309,7 +1321,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
13091321
/* register a new auditd connection */
13101322
err = auditd_set(req_pid,
13111323
NETLINK_CB(skb).portid,
1312-
sock_net(NETLINK_CB(skb).sk));
1324+
sock_net(NETLINK_CB(skb).sk),
1325+
skb, ack);
13131326
if (audit_enabled != AUDIT_OFF)
13141327
audit_log_config_change("audit_pid",
13151328
new_pid,
@@ -1554,9 +1567,10 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
15541567
* Parse the provided skb and deal with any messages that may be present,
15551568
* malformed skbs are discarded.
15561569
*/
1557-
static void audit_receive(struct sk_buff *skb)
1570+
static void audit_receive(struct sk_buff *skb)
15581571
{
15591572
struct nlmsghdr *nlh;
1573+
bool ack;
15601574
/*
15611575
* len MUST be signed for nlmsg_next to be able to dec it below 0
15621576
* if the nlmsg_len was not aligned
@@ -1569,9 +1583,12 @@ static void audit_receive(struct sk_buff *skb)
15691583

15701584
audit_ctl_lock();
15711585
while (nlmsg_ok(nlh, len)) {
1572-
err = audit_receive_msg(skb, nlh);
1573-
/* if err or if this message says it wants a response */
1574-
if (err || (nlh->nlmsg_flags & NLM_F_ACK))
1586+
ack = nlh->nlmsg_flags & NLM_F_ACK;
1587+
err = audit_receive_msg(skb, nlh, &ack);
1588+
1589+
/* send an ack if the user asked for one and audit_receive_msg
1590+
* didn't already do it, or if there was an error. */
1591+
if (ack || err)
15751592
netlink_ack(skb, nlh, err, NULL);
15761593

15771594
nlh = nlmsg_next(nlh, &len);

0 commit comments

Comments
 (0)