aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/audit.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2006-05-22 01:09:24 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2006-06-20 05:25:20 -0400
commit9044e6bca5a4a575d3c068dfccb5651a2d6a13bc (patch)
treee0fa2beb83c3ef4e52cc6c6b28ce3173656f4276 /kernel/audit.c
parentbc0f3b8ebba611291fdaa2864dbffd2d29336c64 (diff)
[PATCH] fix deadlocks in AUDIT_LIST/AUDIT_LIST_RULES
We should not send a pile of replies while holding audit_netlink_mutex since we hold the same mutex when we receive commands. As the result, we can get blocked while sending and sit there holding the mutex while auditctl is unable to send the next command and get around to receiving what we'd sent. Solution: create skb and put them into a queue instead of sending; once we are done, send what we've got on the list. The former can be done synchronously while we are handling AUDIT_LIST or AUDIT_LIST_RULES; we are holding audit_netlink_mutex at that point. The latter is done asynchronously and without messing with audit_netlink_mutex. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/audit.c')
-rw-r--r--kernel/audit.c62
1 files changed, 45 insertions, 17 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index df57b493e1cb..bf74bf02aa4b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -366,6 +366,50 @@ static int kauditd_thread(void *dummy)
366 return 0; 366 return 0;
367} 367}
368 368
369int audit_send_list(void *_dest)
370{
371 struct audit_netlink_list *dest = _dest;
372 int pid = dest->pid;
373 struct sk_buff *skb;
374
375 /* wait for parent to finish and send an ACK */
376 mutex_lock(&audit_netlink_mutex);
377 mutex_unlock(&audit_netlink_mutex);
378
379 while ((skb = __skb_dequeue(&dest->q)) != NULL)
380 netlink_unicast(audit_sock, skb, pid, 0);
381
382 kfree(dest);
383
384 return 0;
385}
386
387struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
388 int multi, void *payload, int size)
389{
390 struct sk_buff *skb;
391 struct nlmsghdr *nlh;
392 int len = NLMSG_SPACE(size);
393 void *data;
394 int flags = multi ? NLM_F_MULTI : 0;
395 int t = done ? NLMSG_DONE : type;
396
397 skb = alloc_skb(len, GFP_KERNEL);
398 if (!skb)
399 return NULL;
400
401 nlh = NLMSG_PUT(skb, pid, seq, t, size);
402 nlh->nlmsg_flags = flags;
403 data = NLMSG_DATA(nlh);
404 memcpy(data, payload, size);
405 return skb;
406
407nlmsg_failure: /* Used by NLMSG_PUT */
408 if (skb)
409 kfree_skb(skb);
410 return NULL;
411}
412
369/** 413/**
370 * audit_send_reply - send an audit reply message via netlink 414 * audit_send_reply - send an audit reply message via netlink
371 * @pid: process id to send reply to 415 * @pid: process id to send reply to
@@ -383,29 +427,13 @@ void audit_send_reply(int pid, int seq, int type, int done, int multi,
383 void *payload, int size) 427 void *payload, int size)
384{ 428{
385 struct sk_buff *skb; 429 struct sk_buff *skb;
386 struct nlmsghdr *nlh; 430 skb = audit_make_reply(pid, seq, type, done, multi, payload, size);
387 int len = NLMSG_SPACE(size);
388 void *data;
389 int flags = multi ? NLM_F_MULTI : 0;
390 int t = done ? NLMSG_DONE : type;
391
392 skb = alloc_skb(len, GFP_KERNEL);
393 if (!skb) 431 if (!skb)
394 return; 432 return;
395
396 nlh = NLMSG_PUT(skb, pid, seq, t, size);
397 nlh->nlmsg_flags = flags;
398 data = NLMSG_DATA(nlh);
399 memcpy(data, payload, size);
400
401 /* Ignore failure. It'll only happen if the sender goes away, 433 /* Ignore failure. It'll only happen if the sender goes away,
402 because our timeout is set to infinite. */ 434 because our timeout is set to infinite. */
403 netlink_unicast(audit_sock, skb, pid, 0); 435 netlink_unicast(audit_sock, skb, pid, 0);
404 return; 436 return;
405
406nlmsg_failure: /* Used by NLMSG_PUT */
407 if (skb)
408 kfree_skb(skb);
409} 437}
410 438
411/* 439/*