From: JP Abgrall Date: Thu, 18 Aug 2011 22:05:47 +0000 (-0700) Subject: netfilter: xt_qtaguid: Fix sockfd_put() call within spinlock X-Git-Tag: firefly_0821_release~7613^2~342 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=97aca38ddd3421bb7f13bf1c41566b23429906ae;p=firefly-linux-kernel-4.4.55.git 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 --- 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 */