Commit b9b3322f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'stable-4.11' of git://git.infradead.org/users/pcmoore/audit

Pull audit fix from Paul Moore:
 "One more small audit fix, this should be the last for v4.11.

  Seth Forshee noticed a problem where the audit retry queue wasn't
  being flushed properly when audit was enabled and the audit daemon
  wasn't running; this patches fixes the problem (see the commit
  description for more details on the change).

  Both Seth and I have tested this and everything looks good"

* 'stable-4.11' of git://git.infradead.org/users/pcmoore/audit:
  audit: make sure we don't let the retry queue grow without bounds
parents 025def92 264d5096
...@@ -160,7 +160,6 @@ static LIST_HEAD(audit_freelist); ...@@ -160,7 +160,6 @@ static LIST_HEAD(audit_freelist);
/* queue msgs to send via kauditd_task */ /* queue msgs to send via kauditd_task */
static struct sk_buff_head audit_queue; static struct sk_buff_head audit_queue;
static void kauditd_hold_skb(struct sk_buff *skb);
/* queue msgs due to temporary unicast send problems */ /* queue msgs due to temporary unicast send problems */
static struct sk_buff_head audit_retry_queue; static struct sk_buff_head audit_retry_queue;
/* queue msgs waiting for new auditd connection */ /* queue msgs waiting for new auditd connection */
...@@ -453,30 +452,6 @@ static void auditd_set(int pid, u32 portid, struct net *net) ...@@ -453,30 +452,6 @@ static void auditd_set(int pid, u32 portid, struct net *net)
spin_unlock_irqrestore(&auditd_conn.lock, flags); spin_unlock_irqrestore(&auditd_conn.lock, flags);
} }
/**
* auditd_reset - Disconnect the auditd connection
*
* Description:
* Break the auditd/kauditd connection and move all the queued records into the
* hold queue in case auditd reconnects.
*/
static void auditd_reset(void)
{
struct sk_buff *skb;
/* if it isn't already broken, break the connection */
rcu_read_lock();
if (auditd_conn.pid)
auditd_set(0, 0, NULL);
rcu_read_unlock();
/* flush all of the main and retry queues to the hold queue */
while ((skb = skb_dequeue(&audit_retry_queue)))
kauditd_hold_skb(skb);
while ((skb = skb_dequeue(&audit_queue)))
kauditd_hold_skb(skb);
}
/** /**
* kauditd_print_skb - Print the audit record to the ring buffer * kauditd_print_skb - Print the audit record to the ring buffer
* @skb: audit record * @skb: audit record
...@@ -505,9 +480,6 @@ static void kauditd_rehold_skb(struct sk_buff *skb) ...@@ -505,9 +480,6 @@ static void kauditd_rehold_skb(struct sk_buff *skb)
{ {
/* put the record back in the queue at the same place */ /* put the record back in the queue at the same place */
skb_queue_head(&audit_hold_queue, skb); skb_queue_head(&audit_hold_queue, skb);
/* fail the auditd connection */
auditd_reset();
} }
/** /**
...@@ -544,9 +516,6 @@ static void kauditd_hold_skb(struct sk_buff *skb) ...@@ -544,9 +516,6 @@ static void kauditd_hold_skb(struct sk_buff *skb)
/* we have no other options - drop the message */ /* we have no other options - drop the message */
audit_log_lost("kauditd hold queue overflow"); audit_log_lost("kauditd hold queue overflow");
kfree_skb(skb); kfree_skb(skb);
/* fail the auditd connection */
auditd_reset();
} }
/** /**
...@@ -566,6 +535,30 @@ static void kauditd_retry_skb(struct sk_buff *skb) ...@@ -566,6 +535,30 @@ static void kauditd_retry_skb(struct sk_buff *skb)
skb_queue_tail(&audit_retry_queue, skb); skb_queue_tail(&audit_retry_queue, skb);
} }
/**
* auditd_reset - Disconnect the auditd connection
*
* Description:
* Break the auditd/kauditd connection and move all the queued records into the
* hold queue in case auditd reconnects.
*/
static void auditd_reset(void)
{
struct sk_buff *skb;
/* if it isn't already broken, break the connection */
rcu_read_lock();
if (auditd_conn.pid)
auditd_set(0, 0, NULL);
rcu_read_unlock();
/* flush all of the main and retry queues to the hold queue */
while ((skb = skb_dequeue(&audit_retry_queue)))
kauditd_hold_skb(skb);
while ((skb = skb_dequeue(&audit_queue)))
kauditd_hold_skb(skb);
}
/** /**
* auditd_send_unicast_skb - Send a record via unicast to auditd * auditd_send_unicast_skb - Send a record via unicast to auditd
* @skb: audit record * @skb: audit record
...@@ -758,6 +751,7 @@ static int kauditd_thread(void *dummy) ...@@ -758,6 +751,7 @@ static int kauditd_thread(void *dummy)
NULL, kauditd_rehold_skb); NULL, kauditd_rehold_skb);
if (rc < 0) { if (rc < 0) {
sk = NULL; sk = NULL;
auditd_reset();
goto main_queue; goto main_queue;
} }
...@@ -767,6 +761,7 @@ static int kauditd_thread(void *dummy) ...@@ -767,6 +761,7 @@ static int kauditd_thread(void *dummy)
NULL, kauditd_hold_skb); NULL, kauditd_hold_skb);
if (rc < 0) { if (rc < 0) {
sk = NULL; sk = NULL;
auditd_reset();
goto main_queue; goto main_queue;
} }
...@@ -775,16 +770,18 @@ static int kauditd_thread(void *dummy) ...@@ -775,16 +770,18 @@ static int kauditd_thread(void *dummy)
* unicast, dump failed record sends to the retry queue; if * unicast, dump failed record sends to the retry queue; if
* sk == NULL due to previous failures we will just do the * sk == NULL due to previous failures we will just do the
* multicast send and move the record to the retry queue */ * multicast send and move the record to the retry queue */
kauditd_send_queue(sk, portid, &audit_queue, 1, rc = kauditd_send_queue(sk, portid, &audit_queue, 1,
kauditd_send_multicast_skb, kauditd_send_multicast_skb,
kauditd_retry_skb); kauditd_retry_skb);
if (sk == NULL || rc < 0)
auditd_reset();
sk = NULL;
/* drop our netns reference, no auditd sends past this line */ /* drop our netns reference, no auditd sends past this line */
if (net) { if (net) {
put_net(net); put_net(net);
net = NULL; net = NULL;
} }
sk = NULL;
/* we have processed all the queues so wake everyone */ /* we have processed all the queues so wake everyone */
wake_up(&audit_backlog_wait); wake_up(&audit_backlog_wait);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment