Commit 639739b5e609a5074839bb22fc061b37baa06269
Committed by
David S. Miller
1 parent
a8e9fd0f74
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
ipv6: fix null pointer dereference in __ip6addrlbl_add
Commit b67bfe0d42cac56c512dd5da4b1b347a23f4b70a ("hlist: drop the node parameter from iterators") changed the behavior of hlist_for_each_entry_safe to leave the p argument NULL. Fix this up by tracking the last argument. Reported-by: Michele Baldessari <michele@acksyn.org> Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org> Cc: Sasha Levin <sasha.levin@oracle.com> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Tested-by: Michele Baldessari <michele@acksyn.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 23 additions and 25 deletions Side-by-side Diff
net/ipv6/addrlabel.c
... | ... | @@ -251,38 +251,36 @@ |
251 | 251 | /* add a label */ |
252 | 252 | static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) |
253 | 253 | { |
254 | + struct hlist_node *n; | |
255 | + struct ip6addrlbl_entry *last = NULL, *p = NULL; | |
254 | 256 | int ret = 0; |
255 | 257 | |
256 | - ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", | |
257 | - __func__, | |
258 | - newp, replace); | |
258 | + ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp, | |
259 | + replace); | |
259 | 260 | |
260 | - if (hlist_empty(&ip6addrlbl_table.head)) { | |
261 | - hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); | |
262 | - } else { | |
263 | - struct hlist_node *n; | |
264 | - struct ip6addrlbl_entry *p = NULL; | |
265 | - hlist_for_each_entry_safe(p, n, | |
266 | - &ip6addrlbl_table.head, list) { | |
267 | - if (p->prefixlen == newp->prefixlen && | |
268 | - net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) && | |
269 | - p->ifindex == newp->ifindex && | |
270 | - ipv6_addr_equal(&p->prefix, &newp->prefix)) { | |
271 | - if (!replace) { | |
272 | - ret = -EEXIST; | |
273 | - goto out; | |
274 | - } | |
275 | - hlist_replace_rcu(&p->list, &newp->list); | |
276 | - ip6addrlbl_put(p); | |
261 | + hlist_for_each_entry_safe(p, n, &ip6addrlbl_table.head, list) { | |
262 | + if (p->prefixlen == newp->prefixlen && | |
263 | + net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) && | |
264 | + p->ifindex == newp->ifindex && | |
265 | + ipv6_addr_equal(&p->prefix, &newp->prefix)) { | |
266 | + if (!replace) { | |
267 | + ret = -EEXIST; | |
277 | 268 | goto out; |
278 | - } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) || | |
279 | - (p->prefixlen < newp->prefixlen)) { | |
280 | - hlist_add_before_rcu(&newp->list, &p->list); | |
281 | - goto out; | |
282 | 269 | } |
270 | + hlist_replace_rcu(&p->list, &newp->list); | |
271 | + ip6addrlbl_put(p); | |
272 | + goto out; | |
273 | + } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) || | |
274 | + (p->prefixlen < newp->prefixlen)) { | |
275 | + hlist_add_before_rcu(&newp->list, &p->list); | |
276 | + goto out; | |
283 | 277 | } |
284 | - hlist_add_after_rcu(&p->list, &newp->list); | |
278 | + last = p; | |
285 | 279 | } |
280 | + if (last) | |
281 | + hlist_add_after_rcu(&last->list, &newp->list); | |
282 | + else | |
283 | + hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); | |
286 | 284 | out: |
287 | 285 | if (!ret) |
288 | 286 | ip6addrlbl_table.seq++; |