From 97aca38ddd3421bb7f13bf1c41566b23429906ae Mon Sep 17 00:00:00 2001 From: JP Abgrall Date: Thu, 18 Aug 2011 15:05:47 -0700 Subject: [PATCH] netfilter: xt_qtaguid: Fix sockfd_put() call within spinlock sockfd_put() risks sleeping. So when doing a delete ctrl command, defer the sockfd_put() and kfree() to outside of the spinlock. Change-Id: I5f8ab51d05888d885b2fbb035f61efa5b7abb88a Signed-off-by: JP Abgrall --- net/netfilter/xt_qtaguid.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index b9dcfde99762..968693cb1bc0 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1325,6 +1325,7 @@ static int ctrl_cmd_delete(const char *input) struct iface_stat *iface_entry; struct rb_node *node; struct sock_tag *st_entry; + struct rb_root st_to_free_tree = RB_ROOT; struct tag_stat *ts_entry; struct tag_counter_set *tcs_entry; @@ -1362,18 +1363,27 @@ static int ctrl_cmd_delete(const char *input) continue; if (!acct_tag || st_entry->tag == tag) { - CT_DEBUG("qtaguid: ctrl_delete(): " - "erase st: sk=%p tag=0x%llx (uid=%u)\n", - st_entry->sk, - st_entry->tag, - entry_uid); rb_erase(&st_entry->sock_node, &sock_tag_tree); - sockfd_put(st_entry->socket); - kfree(st_entry); + /* Can't sockfd_put() within spinlock, do it later. */ + sock_tag_tree_insert(st_entry, &st_to_free_tree); } } spin_unlock_bh(&sock_tag_list_lock); + node = rb_first(&st_to_free_tree); + while (node) { + st_entry = rb_entry(node, struct sock_tag, sock_node); + node = rb_next(node); + CT_DEBUG("qtaguid: ctrl_delete(): " + "erase st: sk=%p tag=0x%llx (uid=%u)\n", + st_entry->sk, + st_entry->tag, + entry_uid); + rb_erase(&st_entry->sock_node, &st_to_free_tree); + sockfd_put(st_entry->socket); + kfree(st_entry); + } + tag = combine_atag_with_uid(acct_tag, uid); /* Delete tag counter-sets */ -- 2.34.1