diff options
author | JP Abgrall <jpa@google.com> | 2011-07-06 20:09:38 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:38:47 -0800 |
commit | d950bc8b0857b6c77950abf646294592445f67f7 (patch) | |
tree | 516e8a067a00992e34bcbd9c09acdad01eff3e52 | |
parent | 9881dd84794835f80622e90575778f2eaf9a7b99 (diff) |
netfitler: xt_qtaguid: add another missing spin_unlock.
This time the symptom is caused by tagging the same socket twice
without untagging it in between.
This would cause it to not unlock, and return.
Signed-off-by: JP Abgrall <jpa@google.com>
-rw-r--r-- | net/netfilter/xt_qtaguid.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 3cacec07fbf7..49ed432d793c 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -997,11 +997,13 @@ static int qtaguid_ctrl_parse(const char *input, int count) sock_tag_entry = get_sock_stat_nl(el_socket->sk); if (!sock_tag_entry) spin_unlock_irqrestore(&sock_tag_list_lock, flags); + /* HERE: The lock is held if there was a matching sock tag entry */ break; default: res = -EINVAL; goto err; } + /* HERE: The lock is held if there was a matching sock tag entry */ /* Process commands */ switch (cmd) { @@ -1009,17 +1011,23 @@ static int qtaguid_ctrl_parse(const char *input, int count) case 't': if (argc < 2) { res = -EINVAL; + /* HERE: The lock is held if there was a matching sock + * tag entry */ goto err_unlock; } if (argc < 3) { acct_tag = 0; } else if (!valid_atag(acct_tag)) { res = -EINVAL; + /* HERE: The lock is held if there was a matching sock + * tag entry */ goto err_unlock; } if (argc < 4) uid = current_fsuid(); if (!sock_tag_entry) { + /* HERE: There is no lock held because there was no + * sock tag entry */ sock_tag_entry = kmalloc(sizeof(*sock_tag_entry), GFP_KERNEL); if (!sock_tag_entry) { @@ -1034,13 +1042,15 @@ static int qtaguid_ctrl_parse(const char *input, int count) uid); spin_lock_irqsave(&sock_tag_list_lock, flags); sock_tag_tree_insert(sock_tag_entry, &sock_tag_tree); - spin_unlock_irqrestore(&sock_tag_list_lock, flags); } else { + /* HERE: The lock is held because there is a matching + * sock tag entry */ /* Just update the acct_tag portion. */ uid_t orig_uid = get_uid_from_tag(sock_tag_entry->tag); sock_tag_entry->tag = combine_atag_with_uid(acct_tag, orig_uid); } + spin_unlock_irqrestore(&sock_tag_list_lock, flags); pr_debug("xt_qtaguid: tag: sock_tag_entry->sk=%p " "...->tag=0x%llx (uid=%u)\n", sock_tag_entry->sk, sock_tag_entry->tag, |