@@ -61,6 +61,7 @@ static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
struct nf_hook_state *state = &entry->state;
/* Release those devices we held, or Alexey will kill me. */
+ dev_put(entry->skb->dev);
dev_put(state->in);
dev_put(state->out);
if (state->sk)
@@ -102,6 +103,7 @@ bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
if (state->sk && !refcount_inc_not_zero(&state->sk->sk_refcnt))
return false;
+ dev_hold(entry->skb->dev);
dev_hold(state->in);
dev_hold(state->out);
@@ -1212,6 +1212,9 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
if (physinif == ifindex || physoutif == ifindex)
return 1;
#endif
+ if (entry->skb->dev)
+ if (entry->skb->dev->ifindex == ifindex)
+ return 1;
if (entry->state.in)
if (entry->state.in->ifindex == ifindex)
return 1;
Before NF_BR_LOCAL_IN, skb->dev is mangled in a way that results in state->in != skb->dev, which can result in UaF when accessing the bridge device if removed while in the queue. Reported-by: Ren Wei <n05ec@lzu.edu.cn> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> --- v2: remove check on NULL skb->dev, per Florian. net/netfilter/nf_queue.c | 2 ++ net/netfilter/nfnetlink_queue.c | 3 +++ 2 files changed, 5 insertions(+)