diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-06-23 04:52:59 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-06-23 04:52:59 -0400 |
commit | a60b33cf59d1c9e0e363287fce799cb23d45660c (patch) | |
tree | 85eb8feea5717cf472a2549e53f59183a95617c5 /net/ipv6 | |
parent | 0f476b6d91a1395bda6464e653ce66ea9bea7167 (diff) | |
parent | 481c5346d0981940ee63037eb53e4e37b0735c10 (diff) |
Merge branch 'linus' into core/softirq
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_input.c | 9 | ||||
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 11 | ||||
-rw-r--r-- | net/ipv6/sit.c | 44 |
3 files changed, 40 insertions, 24 deletions
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 4e5c8615832c..17eb48b8e329 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -102,6 +102,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
102 | if (hdr->version != 6) | 102 | if (hdr->version != 6) |
103 | goto err; | 103 | goto err; |
104 | 104 | ||
105 | /* | ||
106 | * RFC4291 2.5.3 | ||
107 | * A packet received on an interface with a destination address | ||
108 | * of loopback must be dropped. | ||
109 | */ | ||
110 | if (!(dev->flags & IFF_LOOPBACK) && | ||
111 | ipv6_addr_loopback(&hdr->daddr)) | ||
112 | goto err; | ||
113 | |||
105 | skb->transport_header = skb->network_header + sizeof(*hdr); | 114 | skb->transport_header = skb->network_header + sizeof(*hdr); |
106 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); | 115 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); |
107 | 116 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index c042ce19bd14..86e28a75267f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -345,18 +345,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
345 | case IPV6_DSTOPTS: | 345 | case IPV6_DSTOPTS: |
346 | { | 346 | { |
347 | struct ipv6_txoptions *opt; | 347 | struct ipv6_txoptions *opt; |
348 | |||
349 | /* remove any sticky options header with a zero option | ||
350 | * length, per RFC3542. | ||
351 | */ | ||
348 | if (optlen == 0) | 352 | if (optlen == 0) |
349 | optval = NULL; | 353 | optval = NULL; |
354 | else if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
355 | optlen & 0x7 || optlen > 8 * 255) | ||
356 | goto e_inval; | ||
350 | 357 | ||
351 | /* hop-by-hop / destination options are privileged option */ | 358 | /* hop-by-hop / destination options are privileged option */ |
352 | retv = -EPERM; | 359 | retv = -EPERM; |
353 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | 360 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) |
354 | break; | 361 | break; |
355 | 362 | ||
356 | if (optlen < sizeof(struct ipv6_opt_hdr) || | ||
357 | optlen & 0x7 || optlen > 8 * 255) | ||
358 | goto e_inval; | ||
359 | |||
360 | opt = ipv6_renew_options(sk, np->opt, optname, | 363 | opt = ipv6_renew_options(sk, np->opt, optname, |
361 | (struct ipv6_opt_hdr __user *)optval, | 364 | (struct ipv6_opt_hdr __user *)optval, |
362 | optlen); | 365 | optlen); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3de6ffdaedf2..32e871a6c25a 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -222,15 +222,18 @@ __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) | |||
222 | 222 | ||
223 | } | 223 | } |
224 | 224 | ||
225 | static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | 225 | static int ipip6_tunnel_get_prl(struct ip_tunnel *t, |
226 | struct ip_tunnel_prl __user *a) | ||
226 | { | 227 | { |
227 | struct ip_tunnel_prl *kp; | 228 | struct ip_tunnel_prl kprl, *kp; |
228 | struct ip_tunnel_prl_entry *prl; | 229 | struct ip_tunnel_prl_entry *prl; |
229 | unsigned int cmax, c = 0, ca, len; | 230 | unsigned int cmax, c = 0, ca, len; |
230 | int ret = 0; | 231 | int ret = 0; |
231 | 232 | ||
232 | cmax = a->datalen / sizeof(*a); | 233 | if (copy_from_user(&kprl, a, sizeof(kprl))) |
233 | if (cmax > 1 && a->addr != htonl(INADDR_ANY)) | 234 | return -EFAULT; |
235 | cmax = kprl.datalen / sizeof(kprl); | ||
236 | if (cmax > 1 && kprl.addr != htonl(INADDR_ANY)) | ||
234 | cmax = 1; | 237 | cmax = 1; |
235 | 238 | ||
236 | /* For simple GET or for root users, | 239 | /* For simple GET or for root users, |
@@ -261,26 +264,25 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) | |||
261 | for (prl = t->prl; prl; prl = prl->next) { | 264 | for (prl = t->prl; prl; prl = prl->next) { |
262 | if (c > cmax) | 265 | if (c > cmax) |
263 | break; | 266 | break; |
264 | if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr) | 267 | if (kprl.addr != htonl(INADDR_ANY) && prl->addr != kprl.addr) |
265 | continue; | 268 | continue; |
266 | kp[c].addr = prl->addr; | 269 | kp[c].addr = prl->addr; |
267 | kp[c].flags = prl->flags; | 270 | kp[c].flags = prl->flags; |
268 | c++; | 271 | c++; |
269 | if (a->addr != htonl(INADDR_ANY)) | 272 | if (kprl.addr != htonl(INADDR_ANY)) |
270 | break; | 273 | break; |
271 | } | 274 | } |
272 | out: | 275 | out: |
273 | read_unlock(&ipip6_lock); | 276 | read_unlock(&ipip6_lock); |
274 | 277 | ||
275 | len = sizeof(*kp) * c; | 278 | len = sizeof(*kp) * c; |
276 | ret = len ? copy_to_user(a->data, kp, len) : 0; | 279 | ret = 0; |
280 | if ((len && copy_to_user(a + 1, kp, len)) || put_user(len, &a->datalen)) | ||
281 | ret = -EFAULT; | ||
277 | 282 | ||
278 | kfree(kp); | 283 | kfree(kp); |
279 | if (ret) | ||
280 | return -EFAULT; | ||
281 | 284 | ||
282 | a->datalen = len; | 285 | return ret; |
283 | return 0; | ||
284 | } | 286 | } |
285 | 287 | ||
286 | static int | 288 | static int |
@@ -873,11 +875,20 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
873 | break; | 875 | break; |
874 | 876 | ||
875 | case SIOCGETPRL: | 877 | case SIOCGETPRL: |
878 | err = -EINVAL; | ||
879 | if (dev == sitn->fb_tunnel_dev) | ||
880 | goto done; | ||
881 | err = -ENOENT; | ||
882 | if (!(t = netdev_priv(dev))) | ||
883 | goto done; | ||
884 | err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data); | ||
885 | break; | ||
886 | |||
876 | case SIOCADDPRL: | 887 | case SIOCADDPRL: |
877 | case SIOCDELPRL: | 888 | case SIOCDELPRL: |
878 | case SIOCCHGPRL: | 889 | case SIOCCHGPRL: |
879 | err = -EPERM; | 890 | err = -EPERM; |
880 | if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) | 891 | if (!capable(CAP_NET_ADMIN)) |
881 | goto done; | 892 | goto done; |
882 | err = -EINVAL; | 893 | err = -EINVAL; |
883 | if (dev == sitn->fb_tunnel_dev) | 894 | if (dev == sitn->fb_tunnel_dev) |
@@ -890,12 +901,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
890 | goto done; | 901 | goto done; |
891 | 902 | ||
892 | switch (cmd) { | 903 | switch (cmd) { |
893 | case SIOCGETPRL: | ||
894 | err = ipip6_tunnel_get_prl(t, &prl); | ||
895 | if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, | ||
896 | &prl, sizeof(prl))) | ||
897 | err = -EFAULT; | ||
898 | break; | ||
899 | case SIOCDELPRL: | 904 | case SIOCDELPRL: |
900 | err = ipip6_tunnel_del_prl(t, &prl); | 905 | err = ipip6_tunnel_del_prl(t, &prl); |
901 | break; | 906 | break; |
@@ -904,8 +909,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) | |||
904 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); | 909 | err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); |
905 | break; | 910 | break; |
906 | } | 911 | } |
907 | if (cmd != SIOCGETPRL) | 912 | netdev_state_change(dev); |
908 | netdev_state_change(dev); | ||
909 | break; | 913 | break; |
910 | 914 | ||
911 | default: | 915 | default: |