diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-08-05 02:04:17 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 17:53:45 -0400 |
commit | dfdd5fd4e93d98e06be9ac9db84e3b98c6c26706 (patch) | |
tree | 521f60c85516ace4a28db7c1e7a7a04e2a6557a2 /net/ipv4/devinet.c | |
parent | 5c7539781d392629fb40b04aad9a1f197b66cd01 (diff) |
[IPV4]: Convert address deletion to new netlink api
Fixes various unvalidated netlink attributes causing
memory corruptions when left empty by userspace.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r-- | net/ipv4/devinet.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 6b297c8697e6..309640e9ede1 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -430,34 +430,48 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, | |||
430 | 430 | ||
431 | static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 431 | static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
432 | { | 432 | { |
433 | struct rtattr **rta = arg; | 433 | struct nlattr *tb[IFA_MAX+1]; |
434 | struct in_device *in_dev; | 434 | struct in_device *in_dev; |
435 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); | 435 | struct ifaddrmsg *ifm; |
436 | struct in_ifaddr *ifa, **ifap; | 436 | struct in_ifaddr *ifa, **ifap; |
437 | int err = -EINVAL; | ||
437 | 438 | ||
438 | ASSERT_RTNL(); | 439 | ASSERT_RTNL(); |
439 | 440 | ||
440 | if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL) | 441 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); |
441 | goto out; | 442 | if (err < 0) |
443 | goto errout; | ||
444 | |||
445 | ifm = nlmsg_data(nlh); | ||
446 | in_dev = inetdev_by_index(ifm->ifa_index); | ||
447 | if (in_dev == NULL) { | ||
448 | err = -ENODEV; | ||
449 | goto errout; | ||
450 | } | ||
451 | |||
442 | __in_dev_put(in_dev); | 452 | __in_dev_put(in_dev); |
443 | 453 | ||
444 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; | 454 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; |
445 | ifap = &ifa->ifa_next) { | 455 | ifap = &ifa->ifa_next) { |
446 | if ((rta[IFA_LOCAL - 1] && | 456 | if (tb[IFA_LOCAL] && |
447 | memcmp(RTA_DATA(rta[IFA_LOCAL - 1]), | 457 | ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL])) |
448 | &ifa->ifa_local, 4)) || | ||
449 | (rta[IFA_LABEL - 1] && | ||
450 | rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) || | ||
451 | (rta[IFA_ADDRESS - 1] && | ||
452 | (ifm->ifa_prefixlen != ifa->ifa_prefixlen || | ||
453 | !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]), | ||
454 | ifa)))) | ||
455 | continue; | 458 | continue; |
459 | |||
460 | if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label)) | ||
461 | continue; | ||
462 | |||
463 | if (tb[IFA_ADDRESS] && | ||
464 | (ifm->ifa_prefixlen != ifa->ifa_prefixlen || | ||
465 | !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa))) | ||
466 | continue; | ||
467 | |||
456 | inet_del_ifa(in_dev, ifap, 1); | 468 | inet_del_ifa(in_dev, ifap, 1); |
457 | return 0; | 469 | return 0; |
458 | } | 470 | } |
459 | out: | 471 | |
460 | return -EADDRNOTAVAIL; | 472 | err = -EADDRNOTAVAIL; |
473 | errout: | ||
474 | return err; | ||
461 | } | 475 | } |
462 | 476 | ||
463 | static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) | 477 | static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) |