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:
Коммит
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
|
* kauditd_rehold_skb - Handle a audit record send failure in the hold queue
|
||||||
* @skb: audit record
|
* @skb: audit record
|
||||||
|
* @error: error code (unused)
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* This should only be used by the kauditd_thread when it fails to flush the
|
* This should only be used by the kauditd_thread when it fails to flush the
|
||||||
* hold queue.
|
* 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 */
|
/* put the record back in the queue */
|
||||||
skb_queue_head(&audit_hold_queue, skb);
|
skb_queue_tail(&audit_hold_queue, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kauditd_hold_skb - Queue an audit record, waiting for auditd
|
* kauditd_hold_skb - Queue an audit record, waiting for auditd
|
||||||
* @skb: audit record
|
* @skb: audit record
|
||||||
|
* @error: error code
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Queue the audit record, waiting for an instance of auditd. When this
|
* 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
|
* 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.
|
* 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
|
/* 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 */
|
* try to send the message via printk before we go any further */
|
||||||
kauditd_printk_skb(skb);
|
kauditd_printk_skb(skb);
|
||||||
|
|
||||||
/* can we just silently drop the message? */
|
/* can we just silently drop the message? */
|
||||||
if (!audit_default) {
|
if (!audit_default)
|
||||||
kfree_skb(skb);
|
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;
|
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 ||
|
if (!audit_backlog_limit ||
|
||||||
skb_queue_len(&audit_hold_queue) < audit_backlog_limit) {
|
skb_queue_len(&audit_hold_queue) < audit_backlog_limit) {
|
||||||
skb_queue_tail(&audit_hold_queue, skb);
|
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 */
|
/* we have no other options - drop the message */
|
||||||
audit_log_lost("kauditd hold queue overflow");
|
audit_log_lost("kauditd hold queue overflow");
|
||||||
|
drop:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kauditd_retry_skb - Queue an audit record, attempt to send again to auditd
|
* kauditd_retry_skb - Queue an audit record, attempt to send again to auditd
|
||||||
* @skb: audit record
|
* @skb: audit record
|
||||||
|
* @error: error code (unused)
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Not as serious as kauditd_hold_skb() as we still have a connected auditd,
|
* 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
|
* but for some reason we are having problems sending it audit records so
|
||||||
* queue the given record and attempt to resend.
|
* 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
|
if (!audit_backlog_limit ||
|
||||||
* short period of time, before either being sent or moved to the hold
|
skb_queue_len(&audit_retry_queue) < audit_backlog_limit) {
|
||||||
* queue, we don't currently enforce a limit on this queue */
|
|
||||||
skb_queue_tail(&audit_retry_queue, skb);
|
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
|
/* flush the retry queue to the hold queue, but don't touch the main
|
||||||
* queue since we need to process that normally for multicast */
|
* queue since we need to process that normally for multicast */
|
||||||
while ((skb = skb_dequeue(&audit_retry_queue)))
|
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,
|
struct sk_buff_head *queue,
|
||||||
unsigned int retry_limit,
|
unsigned int retry_limit,
|
||||||
void (*skb_hook)(struct sk_buff *skb),
|
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;
|
int rc = 0;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb = NULL;
|
||||||
|
struct sk_buff *skb_tail;
|
||||||
unsigned int failed = 0;
|
unsigned int failed = 0;
|
||||||
|
|
||||||
/* NOTE: kauditd_thread takes care of all our locking, we just use
|
/* NOTE: kauditd_thread takes care of all our locking, we just use
|
||||||
* the netlink info passed to us (e.g. sk and portid) */
|
* 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 */
|
/* call the skb_hook for each skb we touch */
|
||||||
if (skb_hook)
|
if (skb_hook)
|
||||||
(*skb_hook)(skb);
|
(*skb_hook)(skb);
|
||||||
|
@ -731,7 +755,7 @@ static int kauditd_send_queue(struct sock *sk, u32 portid,
|
||||||
/* can we send to anyone via unicast? */
|
/* can we send to anyone via unicast? */
|
||||||
if (!sk) {
|
if (!sk) {
|
||||||
if (err_hook)
|
if (err_hook)
|
||||||
(*err_hook)(skb);
|
(*err_hook)(skb, -ECONNREFUSED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,7 +769,7 @@ retry:
|
||||||
rc == -ECONNREFUSED || rc == -EPERM) {
|
rc == -ECONNREFUSED || rc == -EPERM) {
|
||||||
sk = NULL;
|
sk = NULL;
|
||||||
if (err_hook)
|
if (err_hook)
|
||||||
(*err_hook)(skb);
|
(*err_hook)(skb, rc);
|
||||||
if (rc == -EAGAIN)
|
if (rc == -EAGAIN)
|
||||||
rc = 0;
|
rc = 0;
|
||||||
/* continue to drain the queue */
|
/* continue to drain the queue */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче