[RESEND][BUG][PATCH V3] audit: audit_log_start running on auditd should not stop

2013-12-04 Thread Toshiyuki Okajima
Hi.

Please apply this patch because the problem that audit_receive called by auditd 
process is hung up by other process (systemd) which has already called it is 
fixed.

This patch fixes the problem that auditd hangs up by itself.

Thanks.

---
The backlog cannot be consumed when audit_log_start is running on auditd
even if audit_log_start calls wait_for_auditd to consume it.
The situation is the deadlock because only auditd can consume the backlog.
If the other process needs to send the backlog, it can be also stopped 
by the deadlock.

So, audit_log_start running on auditd should not stop.

You can see the deadlock with the following reproducer:
 # auditctl -a exit,always -S all
 # reboot

Signed-off-by: Toshiyuki Okajima 
Reviewed-by: gaof...@cn.fujitsu.com
---
 kernel/audit.c |   14 --
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/kernel/audit.c b/kernel/audit.c
index 7b0e23a..29cfc94 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1095,7 +1095,8 @@ struct audit_buffer *audit_log_start(struct audit_context 
*ctx, gfp_t gfp_mask,
struct audit_buffer *ab = NULL;
struct timespec t;
unsigned intuninitialized_var(serial);
-   int reserve;
+   int reserve = 5; /* Allow atomic callers to go up to five
+   entries over the normal backlog limit */
unsigned long timeout_start = jiffies;
 
if (audit_initialized != AUDIT_INITIALIZED)
@@ -1104,11 +1105,12 @@ struct audit_buffer *audit_log_start(struct 
audit_context *ctx, gfp_t gfp_mask,
if (unlikely(audit_filter_type(type)))
return NULL;
 
-   if (gfp_mask & __GFP_WAIT)
-   reserve = 0;
-   else
-   reserve = 5; /* Allow atomic callers to go up to five
-   entries over the normal backlog limit */
+   if (gfp_mask & __GFP_WAIT) {
+   if (audit_pid && audit_pid == current->pid)
+   gfp_mask &= ~__GFP_WAIT;
+   else
+   reserve = 0;
+   }
 
while (audit_backlog_limit
   && skb_queue_len(_skb_queue) > audit_backlog_limit + 
reserve) {
-- 
1.5.5.6
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND][BUG][PATCH V3] audit: audit_log_start running on auditd should not stop

2013-12-04 Thread Toshiyuki Okajima
Hi.

Please apply this patch because the problem that audit_receive called by auditd 
process is hung up by other process (systemd) which has already called it is 
fixed.

This patch fixes the problem that auditd hangs up by itself.

Thanks.

---
The backlog cannot be consumed when audit_log_start is running on auditd
even if audit_log_start calls wait_for_auditd to consume it.
The situation is the deadlock because only auditd can consume the backlog.
If the other process needs to send the backlog, it can be also stopped 
by the deadlock.

So, audit_log_start running on auditd should not stop.

You can see the deadlock with the following reproducer:
 # auditctl -a exit,always -S all
 # reboot

Signed-off-by: Toshiyuki Okajima toshi.okaj...@jp.fujitsu.com
Reviewed-by: gaof...@cn.fujitsu.com
---
 kernel/audit.c |   14 --
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/kernel/audit.c b/kernel/audit.c
index 7b0e23a..29cfc94 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1095,7 +1095,8 @@ struct audit_buffer *audit_log_start(struct audit_context 
*ctx, gfp_t gfp_mask,
struct audit_buffer *ab = NULL;
struct timespec t;
unsigned intuninitialized_var(serial);
-   int reserve;
+   int reserve = 5; /* Allow atomic callers to go up to five
+   entries over the normal backlog limit */
unsigned long timeout_start = jiffies;
 
if (audit_initialized != AUDIT_INITIALIZED)
@@ -1104,11 +1105,12 @@ struct audit_buffer *audit_log_start(struct 
audit_context *ctx, gfp_t gfp_mask,
if (unlikely(audit_filter_type(type)))
return NULL;
 
-   if (gfp_mask  __GFP_WAIT)
-   reserve = 0;
-   else
-   reserve = 5; /* Allow atomic callers to go up to five
-   entries over the normal backlog limit */
+   if (gfp_mask  __GFP_WAIT) {
+   if (audit_pid  audit_pid == current-pid)
+   gfp_mask = ~__GFP_WAIT;
+   else
+   reserve = 0;
+   }
 
while (audit_backlog_limit
skb_queue_len(audit_skb_queue)  audit_backlog_limit + 
reserve) {
-- 
1.5.5.6
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/