Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> writes: > On Fri, Jul 10, 2015 at 06:15:06PM -0500, Eric W. Biederman wrote: >> @@ -102,13 +112,35 @@ int nf_register_hook(struct nf_hook_ops *reg) >> #endif >> return 0; >> } >> -EXPORT_SYMBOL(nf_register_hook); >> +EXPORT_SYMBOL(nf_register_net_hook); >> >> -void nf_unregister_hook(struct nf_hook_ops *reg) >> +void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) >> { >> + struct list_head *nf_hook_list; >> + struct nf_hook_ops *elem; >> + >> + nf_hook_list = find_nf_hook_list(net, reg); >> + if (!nf_hook_list) >> + return; >> + >> mutex_lock(&nf_hook_mutex); >> - list_del_rcu(®->list); >> + list_for_each_entry(elem, nf_hook_list, list) { >> + if ((reg->hook == elem->hook) && >> + (reg->dev == elem->dev) && >> + (reg->owner == elem->owner) && >> + (reg->priv == elem->priv) && >> + (reg->pf == elem->pf) && >> + (reg->hooknum == elem->hooknum) && >> + (reg->priority == elem->priority)) { >> + list_del_rcu(&elem->list); >> + break; >> + } >> + } > > I think I found a problem with this code above. > > If we register two hooks from the same module using exactly the same > tuple that identifies this, we delete the hook that we don't want, eg. > > nft add table filter > nft add chain filter test { type filter hook input priority 0\; } > nft add chain filter test2 { type filter hook input priority 0\; } > > then, you delete 'test': > > nft delete chain filter test > > This will delete 'test2' hook instead of 'test' as it will find this > in first place on the list. So we have two adjacent entries on the same chain that perform the exact same action. We delete one of them. I do not see how that is noticable. Registration order plays a small role but especially with the priority bit we don't strongly honor registration order. In your example above we will distinguish between the two chains as nf_hook_ops->priv will point the nf tables chain. So that specific case is at least safe. > I think we should add a cookie field that stores the address of the > original hook object that is passed as parameter, so we are sure we > kill the right hook. I don't believe that is necessary. To the best of my knowledge for a registration to be meaningful we must always change at least one of those fields I am comparing. Typically either priv or hook. It is a real change from what we have been doing but there is a lot of freedom in not needing to keep the original structure around. Eric -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html