mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
audit/stable-5.17 PR 20220131
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmH4I8oUHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXP9zw//ZAU42ylQXvGfLJbCsbZHKq7H/Ljo QKbwlSKh+aP+IXcRxnh9fV3vTkc7LkHZfrhGx35aHlS1HK8XIa/XHHNTPHfaEKai iDiXwICP5j1JysWCKJXu0uhe7juW3ko7+bQyI8MYBAeLKrbC1F04oswSgVNuX2bq aMyD9+GdAv7PiVVw0oc5+hKFS/8q/VRdbCsJmESKUDhthS3hqH8wZJqy37aYIpF1 /yqkvEIts+GzeQrSWvsGL+O720GIyZ8V2/cEH2y+pnGYgoYdlXhD1CccXOOCocb8 M/6uQZTgQiEVf1LMuu/WIW6CzrRQIjOt4SNU0cXLkWlgxAN1p5b9sP+YcncWU23N zbIACFiFVz1ZhxHT0AEVs+thdZrF6CJX0xfsb+GvJJeYy9aw11s7VGlYhaM+1haG 8oeYmtjQ+rjjkEKMUcOWQYxRvCZIsI6z5JlqoFC0zuJda1k3418LyDZARwCUrm1c 6QY35M0HHxa8k7TWtvJ6aopxM4pg+ZL8WS0shULHRqw/NprvYc6KeZc0/VNyFojJ S4wa+Z6rXoYIvGReeDkUOiJjigW78/kyQR2rsxHWaGlDfL8+bALdnorkTbU2G4oG Jl1HQdOSuAeAT/D7w/UmKFXDBPXHU77sLnjxiCDMmbmVY6Vxja/hZD/wy9RyyK4K UAXDJNwhndHsgX4= =sFi4 -----END PGP SIGNATURE----- Merge tag 'audit-pr-20220131' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit Pull audit fix from Paul Moore: "A single audit patch to fix problems relating to audit queuing and system responsiveness when "audit=1" is specified on the kernel command line and the audit daemon is SIGSTOP'd for an extended period of time" * tag 'audit-pr-20220131' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit: audit: improve audit queue handling when "audit=1" on cmdline
This commit is contained in:
commit
61fda95541
@ -541,20 +541,22 @@ static void kauditd_printk_skb(struct sk_buff *skb)
|
||||
/**
|
||||
* kauditd_rehold_skb - Handle a audit record send failure in the hold queue
|
||||
* @skb: audit record
|
||||
* @error: error code (unused)
|
||||
*
|
||||
* Description:
|
||||
* This should only be used by the kauditd_thread when it fails to flush the
|
||||
* hold queue.
|
||||
*/
|
||||
static void kauditd_rehold_skb(struct sk_buff *skb)
|
||||
static void kauditd_rehold_skb(struct sk_buff *skb, __always_unused int error)
|
||||
{
|
||||
/* put the record back in the queue at the same place */
|
||||
skb_queue_head(&audit_hold_queue, skb);
|
||||
/* put the record back in the queue */
|
||||
skb_queue_tail(&audit_hold_queue, skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* kauditd_hold_skb - Queue an audit record, waiting for auditd
|
||||
* @skb: audit record
|
||||
* @error: error code
|
||||
*
|
||||
* Description:
|
||||
* Queue the audit record, waiting for an instance of auditd. When this
|
||||
@ -564,19 +566,31 @@ static void kauditd_rehold_skb(struct sk_buff *skb)
|
||||
* and queue it, if we have room. If we want to hold on to the record, but we
|
||||
* don't have room, record a record lost message.
|
||||
*/
|
||||
static void kauditd_hold_skb(struct sk_buff *skb)
|
||||
static void kauditd_hold_skb(struct sk_buff *skb, int error)
|
||||
{
|
||||
/* at this point it is uncertain if we will ever send this to auditd so
|
||||
* try to send the message via printk before we go any further */
|
||||
kauditd_printk_skb(skb);
|
||||
|
||||
/* can we just silently drop the message? */
|
||||
if (!audit_default) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
if (!audit_default)
|
||||
goto drop;
|
||||
|
||||
/* the hold queue is only for when the daemon goes away completely,
|
||||
* not -EAGAIN failures; if we are in a -EAGAIN state requeue the
|
||||
* record on the retry queue unless it's full, in which case drop it
|
||||
*/
|
||||
if (error == -EAGAIN) {
|
||||
if (!audit_backlog_limit ||
|
||||
skb_queue_len(&audit_retry_queue) < audit_backlog_limit) {
|
||||
skb_queue_tail(&audit_retry_queue, skb);
|
||||
return;
|
||||
}
|
||||
audit_log_lost("kauditd retry queue overflow");
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* if we have room, queue the message */
|
||||
/* if we have room in the hold queue, queue the message */
|
||||
if (!audit_backlog_limit ||
|
||||
skb_queue_len(&audit_hold_queue) < audit_backlog_limit) {
|
||||
skb_queue_tail(&audit_hold_queue, skb);
|
||||
@ -585,24 +599,32 @@ static void kauditd_hold_skb(struct sk_buff *skb)
|
||||
|
||||
/* we have no other options - drop the message */
|
||||
audit_log_lost("kauditd hold queue overflow");
|
||||
drop:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
* kauditd_retry_skb - Queue an audit record, attempt to send again to auditd
|
||||
* @skb: audit record
|
||||
* @error: error code (unused)
|
||||
*
|
||||
* Description:
|
||||
* Not as serious as kauditd_hold_skb() as we still have a connected auditd,
|
||||
* but for some reason we are having problems sending it audit records so
|
||||
* queue the given record and attempt to resend.
|
||||
*/
|
||||
static void kauditd_retry_skb(struct sk_buff *skb)
|
||||
static void kauditd_retry_skb(struct sk_buff *skb, __always_unused int error)
|
||||
{
|
||||
/* NOTE: because records should only live in the retry queue for a
|
||||
* short period of time, before either being sent or moved to the hold
|
||||
* queue, we don't currently enforce a limit on this queue */
|
||||
skb_queue_tail(&audit_retry_queue, skb);
|
||||
if (!audit_backlog_limit ||
|
||||
skb_queue_len(&audit_retry_queue) < audit_backlog_limit) {
|
||||
skb_queue_tail(&audit_retry_queue, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
/* we have to drop the record, send it via printk as a last effort */
|
||||
kauditd_printk_skb(skb);
|
||||
audit_log_lost("kauditd retry queue overflow");
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -640,7 +662,7 @@ static void auditd_reset(const struct auditd_connection *ac)
|
||||
/* flush the retry queue to the hold queue, but don't touch the main
|
||||
* queue since we need to process that normally for multicast */
|
||||
while ((skb = skb_dequeue(&audit_retry_queue)))
|
||||
kauditd_hold_skb(skb);
|
||||
kauditd_hold_skb(skb, -ECONNREFUSED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -714,16 +736,18 @@ static int kauditd_send_queue(struct sock *sk, u32 portid,
|
||||
struct sk_buff_head *queue,
|
||||
unsigned int retry_limit,
|
||||
void (*skb_hook)(struct sk_buff *skb),
|
||||
void (*err_hook)(struct sk_buff *skb))
|
||||
void (*err_hook)(struct sk_buff *skb, int error))
|
||||
{
|
||||
int rc = 0;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sk_buff *skb_tail;
|
||||
unsigned int failed = 0;
|
||||
|
||||
/* NOTE: kauditd_thread takes care of all our locking, we just use
|
||||
* the netlink info passed to us (e.g. sk and portid) */
|
||||
|
||||
while ((skb = skb_dequeue(queue))) {
|
||||
skb_tail = skb_peek_tail(queue);
|
||||
while ((skb != skb_tail) && (skb = skb_dequeue(queue))) {
|
||||
/* call the skb_hook for each skb we touch */
|
||||
if (skb_hook)
|
||||
(*skb_hook)(skb);
|
||||
@ -731,7 +755,7 @@ static int kauditd_send_queue(struct sock *sk, u32 portid,
|
||||
/* can we send to anyone via unicast? */
|
||||
if (!sk) {
|
||||
if (err_hook)
|
||||
(*err_hook)(skb);
|
||||
(*err_hook)(skb, -ECONNREFUSED);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -745,7 +769,7 @@ retry:
|
||||
rc == -ECONNREFUSED || rc == -EPERM) {
|
||||
sk = NULL;
|
||||
if (err_hook)
|
||||
(*err_hook)(skb);
|
||||
(*err_hook)(skb, rc);
|
||||
if (rc == -EAGAIN)
|
||||
rc = 0;
|
||||
/* continue to drain the queue */
|
||||
|
Loading…
Reference in New Issue
Block a user