diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-08-04 23:04:17 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 14:53:45 -0700 |
commit | dfdd5fd4e93d98e06be9ac9db84e3b98c6c26706 (patch) | |
tree | 521f60c85516ace4a28db7c1e7a7a04e2a6557a2 | |
parent | 5c7539781d392629fb40b04aad9a1f197b66cd01 (diff) | |
download | linux-next-dfdd5fd4e93d98e06be9ac9db84e3b98c6c26706.tar.gz |
[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>
-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, static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct rtattr **rta = arg; + struct nlattr *tb[IFA_MAX+1]; struct in_device *in_dev; - struct ifaddrmsg *ifm = NLMSG_DATA(nlh); + struct ifaddrmsg *ifm; struct in_ifaddr *ifa, **ifap; + int err = -EINVAL; ASSERT_RTNL(); - if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL) - goto out; + err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); + if (err < 0) + goto errout; + + ifm = nlmsg_data(nlh); + in_dev = inetdev_by_index(ifm->ifa_index); + if (in_dev == NULL) { + err = -ENODEV; + goto errout; + } + __in_dev_put(in_dev); for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { - if ((rta[IFA_LOCAL - 1] && - memcmp(RTA_DATA(rta[IFA_LOCAL - 1]), - &ifa->ifa_local, 4)) || - (rta[IFA_LABEL - 1] && - rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) || - (rta[IFA_ADDRESS - 1] && - (ifm->ifa_prefixlen != ifa->ifa_prefixlen || - !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]), - ifa)))) + if (tb[IFA_LOCAL] && + ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL])) continue; + + if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label)) + continue; + + if (tb[IFA_ADDRESS] && + (ifm->ifa_prefixlen != ifa->ifa_prefixlen || + !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa))) + continue; + inet_del_ifa(in_dev, ifap, 1); return 0; } -out: - return -EADDRNOTAVAIL; + + err = -EADDRNOTAVAIL; +errout: + return err; } static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) |