diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 19 |
1 files changed, 8 insertions, 11 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 0f84dd7af2c8..ac26d4d960d3 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -427,7 +427,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
427 | /* Get message from skb (based on rtnetlink_rcv_skb). Each message is | 427 | /* Get message from skb (based on rtnetlink_rcv_skb). Each message is |
428 | * processed by audit_receive_msg. Malformed skbs with wrong length are | 428 | * processed by audit_receive_msg. Malformed skbs with wrong length are |
429 | * discarded silently. */ | 429 | * discarded silently. */ |
430 | static int audit_receive_skb(struct sk_buff *skb) | 430 | static void audit_receive_skb(struct sk_buff *skb) |
431 | { | 431 | { |
432 | int err; | 432 | int err; |
433 | struct nlmsghdr *nlh; | 433 | struct nlmsghdr *nlh; |
@@ -436,7 +436,7 @@ static int audit_receive_skb(struct sk_buff *skb) | |||
436 | while (skb->len >= NLMSG_SPACE(0)) { | 436 | while (skb->len >= NLMSG_SPACE(0)) { |
437 | nlh = (struct nlmsghdr *)skb->data; | 437 | nlh = (struct nlmsghdr *)skb->data; |
438 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) | 438 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) |
439 | return 0; | 439 | return; |
440 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | 440 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); |
441 | if (rlen > skb->len) | 441 | if (rlen > skb->len) |
442 | rlen = skb->len; | 442 | rlen = skb->len; |
@@ -446,23 +446,20 @@ static int audit_receive_skb(struct sk_buff *skb) | |||
446 | netlink_ack(skb, nlh, 0); | 446 | netlink_ack(skb, nlh, 0); |
447 | skb_pull(skb, rlen); | 447 | skb_pull(skb, rlen); |
448 | } | 448 | } |
449 | return 0; | ||
450 | } | 449 | } |
451 | 450 | ||
452 | /* Receive messages from netlink socket. */ | 451 | /* Receive messages from netlink socket. */ |
453 | static void audit_receive(struct sock *sk, int length) | 452 | static void audit_receive(struct sock *sk, int length) |
454 | { | 453 | { |
455 | struct sk_buff *skb; | 454 | struct sk_buff *skb; |
455 | unsigned int qlen; | ||
456 | 456 | ||
457 | if (down_trylock(&audit_netlink_sem)) | 457 | down(&audit_netlink_sem); |
458 | return; | ||
459 | 458 | ||
460 | /* FIXME: this must not cause starvation */ | 459 | for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { |
461 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 460 | skb = skb_dequeue(&sk->sk_receive_queue); |
462 | if (audit_receive_skb(skb) && skb->len) | 461 | audit_receive_skb(skb); |
463 | skb_queue_head(&sk->sk_receive_queue, skb); | 462 | kfree_skb(skb); |
464 | else | ||
465 | kfree_skb(skb); | ||
466 | } | 463 | } |
467 | up(&audit_netlink_sem); | 464 | up(&audit_netlink_sem); |
468 | } | 465 | } |