History

netfilter: nfnetlink_log: cope with concurrent instance destruction

Instances are refcounted. However, only memory release happens on the 1 -> 0 transition; the unlink from hashes can occur with any refcount. Uncooperative userspace can force a situation where a queue is pending for destruction from netlink event while a different socket with same portid processes an UNBIND request. With right timing, this will unhash the instance again: Oops: general protection fault, [..] Call Trace: <TASK> nfulnl_recv_config+0x31a/0xd50 nfnetlink_rcv_msg+0x7c2/0xeb0

Florian Westphal committed 2 months ago

Commit 387d7441 parent 2c018cc1 file · +9 −4Browse files

Unified · Split

net/netfilter/nfnetlink_log.c+9−4
@@ -228,13 +228,18 @@ static void __nfulnl_flush(struct nfulnl_instance *inst); · 227 unmodified lines
228static void228static void
229__instance_destroy(struct nfulnl_instance *inst)229__instance_destroy(struct nfulnl_instance *inst)
230{230{
231 spin_lock(&inst->lock);
232 if (inst->copy_mode == NFULNL_COPY_DISABLED) {
233 /* attempt to UNBIND a queue already pending
234 * destruction via netlink close event. Ignore.
235 */
236 spin_unlock(&inst->lock);
237 return;
238 }
239
231 /* first pull it out of the global list */240 /* first pull it out of the global list */
232 hlist_del_rcu(&inst->hlist);241 hlist_del_rcu(&inst->hlist);
233 242
234 /* then flush all pending packets from skb */
235
236 spin_lock(&inst->lock);
237
238 /* lockless readers wont be able to use us */243 /* lockless readers wont be able to use us */
239 inst->copy_mode = NFULNL_COPY_DISABLED;244 inst->copy_mode = NFULNL_COPY_DISABLED;
240 245