diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/fib_frontend.c | 5 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 28 | ||||
-rw-r--r-- | net/ipv4/raw.c | 24 | ||||
-rw-r--r-- | net/ipv4/route.c | 8 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 6 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 |
6 files changed, 45 insertions, 30 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index e2f950592566..aa00398be80e 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -229,14 +229,17 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, | |||
229 | */ | 229 | */ |
230 | 230 | ||
231 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | 231 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, |
232 | struct net_device *dev, __be32 *spec_dst, u32 *itag) | 232 | struct net_device *dev, __be32 *spec_dst, |
233 | u32 *itag, u32 mark) | ||
233 | { | 234 | { |
234 | struct in_device *in_dev; | 235 | struct in_device *in_dev; |
235 | struct flowi fl = { .nl_u = { .ip4_u = | 236 | struct flowi fl = { .nl_u = { .ip4_u = |
236 | { .daddr = src, | 237 | { .daddr = src, |
237 | .saddr = dst, | 238 | .saddr = dst, |
238 | .tos = tos } }, | 239 | .tos = tos } }, |
240 | .mark = mark, | ||
239 | .iif = oif }; | 241 | .iif = oif }; |
242 | |||
240 | struct fib_result res; | 243 | struct fib_result res; |
241 | int no_addr, rpf; | 244 | int no_addr, rpf; |
242 | int ret; | 245 | int ret; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 41ada9904d31..143333852624 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1464,7 +1464,7 @@ static void ipgre_tap_setup(struct net_device *dev) | |||
1464 | 1464 | ||
1465 | ether_setup(dev); | 1465 | ether_setup(dev); |
1466 | 1466 | ||
1467 | dev->netdev_ops = &ipgre_netdev_ops; | 1467 | dev->netdev_ops = &ipgre_tap_netdev_ops; |
1468 | dev->destructor = free_netdev; | 1468 | dev->destructor = free_netdev; |
1469 | 1469 | ||
1470 | dev->iflink = 0; | 1470 | dev->iflink = 0; |
@@ -1525,25 +1525,29 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], | |||
1525 | if (t->dev != dev) | 1525 | if (t->dev != dev) |
1526 | return -EEXIST; | 1526 | return -EEXIST; |
1527 | } else { | 1527 | } else { |
1528 | unsigned nflags = 0; | ||
1529 | |||
1530 | t = nt; | 1528 | t = nt; |
1531 | 1529 | ||
1532 | if (ipv4_is_multicast(p.iph.daddr)) | 1530 | if (dev->type != ARPHRD_ETHER) { |
1533 | nflags = IFF_BROADCAST; | 1531 | unsigned nflags = 0; |
1534 | else if (p.iph.daddr) | ||
1535 | nflags = IFF_POINTOPOINT; | ||
1536 | 1532 | ||
1537 | if ((dev->flags ^ nflags) & | 1533 | if (ipv4_is_multicast(p.iph.daddr)) |
1538 | (IFF_POINTOPOINT | IFF_BROADCAST)) | 1534 | nflags = IFF_BROADCAST; |
1539 | return -EINVAL; | 1535 | else if (p.iph.daddr) |
1536 | nflags = IFF_POINTOPOINT; | ||
1537 | |||
1538 | if ((dev->flags ^ nflags) & | ||
1539 | (IFF_POINTOPOINT | IFF_BROADCAST)) | ||
1540 | return -EINVAL; | ||
1541 | } | ||
1540 | 1542 | ||
1541 | ipgre_tunnel_unlink(ign, t); | 1543 | ipgre_tunnel_unlink(ign, t); |
1542 | t->parms.iph.saddr = p.iph.saddr; | 1544 | t->parms.iph.saddr = p.iph.saddr; |
1543 | t->parms.iph.daddr = p.iph.daddr; | 1545 | t->parms.iph.daddr = p.iph.daddr; |
1544 | t->parms.i_key = p.i_key; | 1546 | t->parms.i_key = p.i_key; |
1545 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 1547 | if (dev->type != ARPHRD_ETHER) { |
1546 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 1548 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
1549 | memcpy(dev->broadcast, &p.iph.daddr, 4); | ||
1550 | } | ||
1547 | ipgre_tunnel_link(ign, t); | 1551 | ipgre_tunnel_link(ign, t); |
1548 | netdev_state_change(dev); | 1552 | netdev_state_change(dev); |
1549 | } | 1553 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 757c9171e7c2..ab996f9c0fe0 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -352,13 +352,24 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, | |||
352 | skb->ip_summed = CHECKSUM_NONE; | 352 | skb->ip_summed = CHECKSUM_NONE; |
353 | 353 | ||
354 | skb->transport_header = skb->network_header; | 354 | skb->transport_header = skb->network_header; |
355 | err = memcpy_fromiovecend((void *)iph, from, 0, length); | 355 | err = -EFAULT; |
356 | if (err) | 356 | if (memcpy_fromiovecend((void *)iph, from, 0, length)) |
357 | goto error_fault; | 357 | goto error_free; |
358 | 358 | ||
359 | /* We don't modify invalid header */ | ||
360 | iphlen = iph->ihl * 4; | 359 | iphlen = iph->ihl * 4; |
361 | if (iphlen >= sizeof(*iph) && iphlen <= length) { | 360 | |
361 | /* | ||
362 | * We don't want to modify the ip header, but we do need to | ||
363 | * be sure that it won't cause problems later along the network | ||
364 | * stack. Specifically we want to make sure that iph->ihl is a | ||
365 | * sane value. If ihl points beyond the length of the buffer passed | ||
366 | * in, reject the frame as invalid | ||
367 | */ | ||
368 | err = -EINVAL; | ||
369 | if (iphlen > length) | ||
370 | goto error_free; | ||
371 | |||
372 | if (iphlen >= sizeof(*iph)) { | ||
362 | if (!iph->saddr) | 373 | if (!iph->saddr) |
363 | iph->saddr = rt->rt_src; | 374 | iph->saddr = rt->rt_src; |
364 | iph->check = 0; | 375 | iph->check = 0; |
@@ -381,8 +392,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, | |||
381 | out: | 392 | out: |
382 | return 0; | 393 | return 0; |
383 | 394 | ||
384 | error_fault: | 395 | error_free: |
385 | err = -EFAULT; | ||
386 | kfree_skb(skb); | 396 | kfree_skb(skb); |
387 | error: | 397 | error: |
388 | IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); | 398 | IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index bb4199252026..5b1050a5d874 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1854,7 +1854,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1854 | goto e_inval; | 1854 | goto e_inval; |
1855 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 1855 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
1856 | } else if (fib_validate_source(saddr, 0, tos, 0, | 1856 | } else if (fib_validate_source(saddr, 0, tos, 0, |
1857 | dev, &spec_dst, &itag) < 0) | 1857 | dev, &spec_dst, &itag, 0) < 0) |
1858 | goto e_inval; | 1858 | goto e_inval; |
1859 | 1859 | ||
1860 | rth = dst_alloc(&ipv4_dst_ops); | 1860 | rth = dst_alloc(&ipv4_dst_ops); |
@@ -1967,7 +1967,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1967 | 1967 | ||
1968 | 1968 | ||
1969 | err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), | 1969 | err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), |
1970 | in_dev->dev, &spec_dst, &itag); | 1970 | in_dev->dev, &spec_dst, &itag, skb->mark); |
1971 | if (err < 0) { | 1971 | if (err < 0) { |
1972 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, | 1972 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, |
1973 | saddr); | 1973 | saddr); |
@@ -2141,7 +2141,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2141 | int result; | 2141 | int result; |
2142 | result = fib_validate_source(saddr, daddr, tos, | 2142 | result = fib_validate_source(saddr, daddr, tos, |
2143 | net->loopback_dev->ifindex, | 2143 | net->loopback_dev->ifindex, |
2144 | dev, &spec_dst, &itag); | 2144 | dev, &spec_dst, &itag, skb->mark); |
2145 | if (result < 0) | 2145 | if (result < 0) |
2146 | goto martian_source; | 2146 | goto martian_source; |
2147 | if (result) | 2147 | if (result) |
@@ -2170,7 +2170,7 @@ brd_input: | |||
2170 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 2170 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
2171 | else { | 2171 | else { |
2172 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, | 2172 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, |
2173 | &itag); | 2173 | &itag, skb->mark); |
2174 | if (err < 0) | 2174 | if (err < 0) |
2175 | goto martian_source; | 2175 | goto martian_source; |
2176 | if (err) | 2176 | if (err) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 90b2e0649bfb..98440ad82558 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1442,9 +1442,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1442 | goto found_ok_skb; | 1442 | goto found_ok_skb; |
1443 | if (tcp_hdr(skb)->fin) | 1443 | if (tcp_hdr(skb)->fin) |
1444 | goto found_fin_ok; | 1444 | goto found_fin_ok; |
1445 | if (WARN_ON(!(flags & MSG_PEEK))) | 1445 | WARN(!(flags & MSG_PEEK), KERN_INFO "recvmsg bug 2: " |
1446 | printk(KERN_INFO "recvmsg bug 2: copied %X " | 1446 | "copied %X seq %X\n", *seq, |
1447 | "seq %X\n", *seq, TCP_SKB_CB(skb)->seq); | 1447 | TCP_SKB_CB(skb)->seq); |
1448 | } | 1448 | } |
1449 | 1449 | ||
1450 | /* Well, if we have backlog, try to process it now yet. */ | 1450 | /* Well, if we have backlog, try to process it now yet. */ |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d0d436d6216c..0fa9f70e4b19 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -999,9 +999,7 @@ try_again: | |||
999 | err = ulen; | 999 | err = ulen; |
1000 | 1000 | ||
1001 | out_free: | 1001 | out_free: |
1002 | lock_sock(sk); | 1002 | skb_free_datagram_locked(sk, skb); |
1003 | skb_free_datagram(sk, skb); | ||
1004 | release_sock(sk); | ||
1005 | out: | 1003 | out: |
1006 | return err; | 1004 | return err; |
1007 | 1005 | ||