Re: Possible netfilter-related memory corruption in 2.6.37

Patrick McHardy
2011-02-14T16:24:37Z

[-- Attachment #1: Type: text/plain, Size: 1130 bytes --]

Am 14.02.2011 16:50, schrieb Eric Dumazet:
> Le lundi 14 février 2011 à 16:18 +0100, Jan Engelhardt a écrit :
>> On Monday 2011-02-14 16:11, Eric Dumazet wrote:
>>
>>> Le lundi 14 février 2011 à 16:58 +0200, Avi Kivity a écrit :
>>>> We see severe memory corruption in kvm while used in conjunction with
>>>> bridge/netfilter. Enabling slab debugging points the finger at a
>>>> netfilter chain invoked from the bridge code.
>>>>
>>>> Can someone take a look?
>>>>
>>>> https://bugzilla.kernel.org/show_bug.cgi?id=27052
>>
>> Maybe looks familiar to https://lkml.org/lkml/2011/2/3/147
>
> Are you sure Jan ?
>
> IMHO it looks like in your case, a NULL ->hook() is called, from
> nf_iterate()
>
> BTW, list_for_each_continue_rcu() really should be converted to
> list_for_each_entry_continue_rcu()
>
> This is a bit ugly :
>
> list_for_each_continue_rcu(*i, head) {
> struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
>
> Also, I wonder if RCU rules are respected in nf_iterate().
> For example this line is really suspicious :
>
> *i = (*i)->prev;

Yeah, that definitely looks wrong. How about this instead?

[-- Attachment #2: x --]
[-- Type: text/plain, Size: 640 bytes --]

diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 1e00bf7..899b71c 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -133,6 +133,7 @@ unsigned int nf_iterate(struct list_head *head,

/* Optimization: we don't need to hold module
reference here, since function can't sleep. --RR */
+repeat:
verdict = elem->hook(hook, skb, indev, outdev, okfn);
if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
@@ -145,7 +146,7 @@ unsigned int nf_iterate(struct list_head *head,
#endif
if (verdict != NF_REPEAT)
return verdict;
- *i = (*i)->prev;
+ goto repeat;
}
}
return NF_ACCEPT;