Commit 639739b5 authored by Hannes Frederic Sowa's avatar Hannes Frederic Sowa Committed by David S. Miller

ipv6: fix null pointer dereference in __ip6addrlbl_add

Commit b67bfe0d ("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: default avatarMichele Baldessari <michele@acksyn.org>
Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Cc: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Tested-by: default avatarMichele Baldessari <michele@acksyn.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a8e9fd0f
...@@ -251,19 +251,14 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net, ...@@ -251,19 +251,14 @@ static struct ip6addrlbl_entry *ip6addrlbl_alloc(struct net *net,
/* add a label */ /* add a label */
static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
{ {
struct hlist_node *n;
struct ip6addrlbl_entry *last = NULL, *p = NULL;
int ret = 0; int ret = 0;
ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp,
__func__, replace);
newp, replace);
if (hlist_empty(&ip6addrlbl_table.head)) { hlist_for_each_entry_safe(p, n, &ip6addrlbl_table.head, list) {
hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
} else {
struct hlist_node *n;
struct ip6addrlbl_entry *p = NULL;
hlist_for_each_entry_safe(p, n,
&ip6addrlbl_table.head, list) {
if (p->prefixlen == newp->prefixlen && if (p->prefixlen == newp->prefixlen &&
net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) && net_eq(ip6addrlbl_net(p), ip6addrlbl_net(newp)) &&
p->ifindex == newp->ifindex && p->ifindex == newp->ifindex &&
...@@ -280,9 +275,12 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) ...@@ -280,9 +275,12 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace)
hlist_add_before_rcu(&newp->list, &p->list); hlist_add_before_rcu(&newp->list, &p->list);
goto out; goto out;
} }
last = p;
} }
hlist_add_after_rcu(&p->list, &newp->list); if (last)
} hlist_add_after_rcu(&last->list, &newp->list);
else
hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head);
out: out:
if (!ret) if (!ret)
ip6addrlbl_table.seq++; ip6addrlbl_table.seq++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment