aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-10-31 11:08:31 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-31 11:08:31 -0500
commit612b322ade7954a1d984fa410a70d4ae50f75c0d (patch)
tree1e8d6cf698148c5fa23870d81a51eb5a460662e3
parentd2c59a22dd7c0a59dfff60a8e9910f76f308b9f2 (diff)
parent1b7c2dbc07bf0663a41e3dc838992930019f08fd (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: [IPV6]: fix flowlabel seqfile handling [IPV6]: return EINVAL for invalid address with flowlabel lease request [SCTP]: Remove temporary associations from backlog and hash. [SCTP]: Correctly set IP id for SCTP traffic [NetLabel]: protect the CIPSOv4 socket option from setsockopt() [NETFILTER]: ip_tables: compat code module refcounting fix [NETFILTER]: nf_conntrack: add missing unlock in get_next_corpse() [NETFILTER]: ip_tables: compat error way cleanup [NETFILTER]: Missed and reordered checks in {arp,ip,ip6}_tables [NETFILTER]: remove masq/NAT from ip6tables Kconfig help [IPV6]: fix lockup via /proc/net/ip6_flowlabel [NET]: fix uaccess handling [SCTP]: Always linearise packet on input [ETH1394]: Fix unaligned accesses. [DCCP]: fix printk format warnings [NET]: Fix segmentation of linear packets [XFRM] xfrm_user: Fix unaligned accesses. [APPLETALK]: Fix potential OOPS in atalk_sendmsg(). [NET] sealevel: uses arp_broken_ops
-rw-r--r--drivers/ieee1394/eth1394.c20
-rw-r--r--drivers/net/wan/Kconfig2
-rw-r--r--net/appletalk/ddp.c2
-rw-r--r--net/core/skbuff.c9
-rw-r--r--net/dccp/ccids/ccid2.c18
-rw-r--r--net/ipv4/cipso_ipv4.c7
-rw-r--r--net/ipv4/ip_options.c2
-rw-r--r--net/ipv4/netfilter/arp_tables.c25
-rw-r--r--net/ipv4/netfilter/ip_tables.c67
-rw-r--r--net/ipv4/raw.c17
-rw-r--r--net/ipv6/ip6_flowlabel.c24
-rw-r--r--net/ipv6/netfilter/Kconfig2
-rw-r--r--net/ipv6/netfilter/ip6_tables.c24
-rw-r--r--net/ipv6/raw.c17
-rw-r--r--net/netfilter/nf_conntrack_core.c3
-rw-r--r--net/netlink/af_netlink.c5
-rw-r--r--net/sctp/associola.c15
-rw-r--r--net/sctp/endpointola.c7
-rw-r--r--net/sctp/input.c9
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/sctp/socket.c9
-rw-r--r--net/xfrm/xfrm_user.c4
-rw-r--r--security/selinux/hooks.c8
-rw-r--r--security/selinux/include/selinux_netlabel.h10
-rw-r--r--security/selinux/ss/services.c37
25 files changed, 229 insertions, 116 deletions
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 8a7b8fab6238..31e5cc49d61a 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -64,6 +64,7 @@
64#include <linux/ethtool.h> 64#include <linux/ethtool.h>
65#include <asm/uaccess.h> 65#include <asm/uaccess.h>
66#include <asm/delay.h> 66#include <asm/delay.h>
67#include <asm/unaligned.h>
67#include <net/arp.h> 68#include <net/arp.h>
68 69
69#include "config_roms.h" 70#include "config_roms.h"
@@ -491,7 +492,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
491 int i; 492 int i;
492 struct eth1394_priv *priv = netdev_priv(dev); 493 struct eth1394_priv *priv = netdev_priv(dev);
493 struct hpsb_host *host = priv->host; 494 struct hpsb_host *host = priv->host;
494 u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3])); 495 u64 guid = get_unaligned((u64*)&(host->csr.rom->bus_info_data[3]));
495 u16 maxpayload = 1 << (host->csr.max_rec + 1); 496 u16 maxpayload = 1 << (host->csr.max_rec + 1);
496 int max_speed = IEEE1394_SPEED_MAX; 497 int max_speed = IEEE1394_SPEED_MAX;
497 498
@@ -514,8 +515,8 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu)
514 ETHER1394_GASP_OVERHEAD))); 515 ETHER1394_GASP_OVERHEAD)));
515 516
516 /* Set our hardware address while we're at it */ 517 /* Set our hardware address while we're at it */
517 *(u64*)dev->dev_addr = guid; 518 memcpy(dev->dev_addr, &guid, sizeof(u64));
518 *(u64*)dev->broadcast = ~0x0ULL; 519 memset(dev->broadcast, 0xff, sizeof(u64));
519 } 520 }
520 521
521 spin_unlock_irqrestore (&priv->lock, flags); 522 spin_unlock_irqrestore (&priv->lock, flags);
@@ -894,6 +895,7 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb,
894 u16 maxpayload; 895 u16 maxpayload;
895 struct eth1394_node_ref *node; 896 struct eth1394_node_ref *node;
896 struct eth1394_node_info *node_info; 897 struct eth1394_node_info *node_info;
898 __be64 guid;
897 899
898 /* Sanity check. MacOSX seems to be sending us 131 in this 900 /* Sanity check. MacOSX seems to be sending us 131 in this
899 * field (atleast on my Panther G5). Not sure why. */ 901 * field (atleast on my Panther G5). Not sure why. */
@@ -902,8 +904,9 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb,
902 904
903 maxpayload = min(eth1394_speedto_maxpayload[sspd], (u16)(1 << (max_rec + 1))); 905 maxpayload = min(eth1394_speedto_maxpayload[sspd], (u16)(1 << (max_rec + 1)));
904 906
907 guid = get_unaligned(&arp1394->s_uniq_id);
905 node = eth1394_find_node_guid(&priv->ip_node_list, 908 node = eth1394_find_node_guid(&priv->ip_node_list,
906 be64_to_cpu(arp1394->s_uniq_id)); 909 be64_to_cpu(guid));
907 if (!node) { 910 if (!node) {
908 return 0; 911 return 0;
909 } 912 }
@@ -931,10 +934,9 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb,
931 arp_ptr += arp->ar_pln; /* skip over sender IP addr */ 934 arp_ptr += arp->ar_pln; /* skip over sender IP addr */
932 935
933 if (arp->ar_op == htons(ARPOP_REQUEST)) 936 if (arp->ar_op == htons(ARPOP_REQUEST))
934 /* just set ARP req target unique ID to 0 */ 937 memset(arp_ptr, 0, sizeof(u64));
935 *((u64*)arp_ptr) = 0;
936 else 938 else
937 *((u64*)arp_ptr) = *((u64*)dev->dev_addr); 939 memcpy(arp_ptr, dev->dev_addr, sizeof(u64));
938 } 940 }
939 941
940 /* Now add the ethernet header. */ 942 /* Now add the ethernet header. */
@@ -1675,8 +1677,10 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev)
1675 if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) 1677 if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
1676 priv->bc_dgl++; 1678 priv->bc_dgl++;
1677 } else { 1679 } else {
1680 __be64 guid = get_unaligned((u64 *)eth->h_dest);
1681
1678 node = eth1394_find_node_guid(&priv->ip_node_list, 1682 node = eth1394_find_node_guid(&priv->ip_node_list,
1679 be64_to_cpu(*(u64*)eth->h_dest)); 1683 be64_to_cpu(guid));
1680 if (!node) { 1684 if (!node) {
1681 ret = -EAGAIN; 1685 ret = -EAGAIN;
1682 goto fail; 1686 goto fail;
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 58b7efbb0750..b5d0d7fb647a 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -127,7 +127,7 @@ config LANMEDIA
127# There is no way to detect a Sealevel board. Force it modular 127# There is no way to detect a Sealevel board. Force it modular
128config SEALEVEL_4021 128config SEALEVEL_4021
129 tristate "Sealevel Systems 4021 support" 129 tristate "Sealevel Systems 4021 support"
130 depends on WAN && ISA && m && ISA_DMA_API 130 depends on WAN && ISA && m && ISA_DMA_API && INET
131 help 131 help
132 This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. 132 This is a driver for the Sealevel Systems ACB 56 serial I/O adapter.
133 133
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 708e2e0371af..485e35c3b28b 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1584,7 +1584,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1584 1584
1585 if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { 1585 if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) {
1586 rt = atrtr_find(&usat->sat_addr); 1586 rt = atrtr_find(&usat->sat_addr);
1587 dev = rt->dev;
1588 } else { 1587 } else {
1589 struct atalk_addr at_hint; 1588 struct atalk_addr at_hint;
1590 1589
@@ -1592,7 +1591,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1592 at_hint.s_net = at->src_net; 1591 at_hint.s_net = at->src_net;
1593 1592
1594 rt = atrtr_find(&at_hint); 1593 rt = atrtr_find(&at_hint);
1595 dev = rt->dev;
1596 } 1594 }
1597 if (!rt) 1595 if (!rt)
1598 return -ENETUNREACH; 1596 return -ENETUNREACH;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3c23760c5827..f735455dc5d1 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1946,7 +1946,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
1946 do { 1946 do {
1947 struct sk_buff *nskb; 1947 struct sk_buff *nskb;
1948 skb_frag_t *frag; 1948 skb_frag_t *frag;
1949 int hsize, nsize; 1949 int hsize;
1950 int k; 1950 int k;
1951 int size; 1951 int size;
1952 1952
@@ -1957,11 +1957,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
1957 hsize = skb_headlen(skb) - offset; 1957 hsize = skb_headlen(skb) - offset;
1958 if (hsize < 0) 1958 if (hsize < 0)
1959 hsize = 0; 1959 hsize = 0;
1960 nsize = hsize + doffset; 1960 if (hsize > len || !sg)
1961 if (nsize > len + doffset || !sg) 1961 hsize = len;
1962 nsize = len + doffset;
1963 1962
1964 nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); 1963 nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC);
1965 if (unlikely(!nskb)) 1964 if (unlikely(!nskb))
1966 goto err; 1965 goto err;
1967 1966
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 2fbb84bf4e26..162032baeac0 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -352,14 +352,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len)
352 352
353#ifdef CONFIG_IP_DCCP_CCID2_DEBUG 353#ifdef CONFIG_IP_DCCP_CCID2_DEBUG
354 ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); 354 ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe);
355 ccid2_pr_debug("Sent: seq=%llu\n", seq); 355 ccid2_pr_debug("Sent: seq=%llu\n", (unsigned long long)seq);
356 do { 356 do {
357 struct ccid2_seq *seqp = hctx->ccid2hctx_seqt; 357 struct ccid2_seq *seqp = hctx->ccid2hctx_seqt;
358 358
359 while (seqp != hctx->ccid2hctx_seqh) { 359 while (seqp != hctx->ccid2hctx_seqh) {
360 ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", 360 ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n",
361 seqp->ccid2s_seq, seqp->ccid2s_acked, 361 (unsigned long long)seqp->ccid2s_seq,
362 seqp->ccid2s_sent); 362 seqp->ccid2s_acked, seqp->ccid2s_sent);
363 seqp = seqp->ccid2s_next; 363 seqp = seqp->ccid2s_next;
364 } 364 }
365 } while (0); 365 } while (0);
@@ -480,7 +480,8 @@ static inline void ccid2_new_ack(struct sock *sk,
480 /* first measurement */ 480 /* first measurement */
481 if (hctx->ccid2hctx_srtt == -1) { 481 if (hctx->ccid2hctx_srtt == -1) {
482 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", 482 ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n",
483 r, jiffies, seqp->ccid2s_seq); 483 r, jiffies,
484 (unsigned long long)seqp->ccid2s_seq);
484 ccid2_change_srtt(hctx, r); 485 ccid2_change_srtt(hctx, r);
485 hctx->ccid2hctx_rttvar = r >> 1; 486 hctx->ccid2hctx_rttvar = r >> 1;
486 } else { 487 } else {
@@ -636,8 +637,9 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
636 u64 ackno_end_rl; 637 u64 ackno_end_rl;
637 638
638 dccp_set_seqno(&ackno_end_rl, ackno - rl); 639 dccp_set_seqno(&ackno_end_rl, ackno - rl);
639 ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno, 640 ccid2_pr_debug("ackvec start:%llu end:%llu\n",
640 ackno_end_rl); 641 (unsigned long long)ackno,
642 (unsigned long long)ackno_end_rl);
641 /* if the seqno we are analyzing is larger than the 643 /* if the seqno we are analyzing is larger than the
642 * current ackno, then move towards the tail of our 644 * current ackno, then move towards the tail of our
643 * seqnos. 645 * seqnos.
@@ -672,7 +674,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
672 674
673 seqp->ccid2s_acked = 1; 675 seqp->ccid2s_acked = 1;
674 ccid2_pr_debug("Got ack for %llu\n", 676 ccid2_pr_debug("Got ack for %llu\n",
675 seqp->ccid2s_seq); 677 (unsigned long long)seqp->ccid2s_seq);
676 ccid2_hc_tx_dec_pipe(sk); 678 ccid2_hc_tx_dec_pipe(sk);
677 } 679 }
678 if (seqp == hctx->ccid2hctx_seqt) { 680 if (seqp == hctx->ccid2hctx_seqt) {
@@ -718,7 +720,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
718 while (1) { 720 while (1) {
719 if (!seqp->ccid2s_acked) { 721 if (!seqp->ccid2s_acked) {
720 ccid2_pr_debug("Packet lost: %llu\n", 722 ccid2_pr_debug("Packet lost: %llu\n",
721 seqp->ccid2s_seq); 723 (unsigned long long)seqp->ccid2s_seq);
722 /* XXX need to traverse from tail -> head in 724 /* XXX need to traverse from tail -> head in
723 * order to detect multiple congestion events in 725 * order to detect multiple congestion events in
724 * one ack vector. 726 * one ack vector.
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index e2077a3aa8c0..6460233407c7 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1307,7 +1307,8 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1307 1307
1308 /* We can't use ip_options_get() directly because it makes a call to 1308 /* We can't use ip_options_get() directly because it makes a call to
1309 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and 1309 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
1310 * we can't block here. */ 1310 * we won't always have CAP_NET_RAW even though we _always_ want to
1311 * set the IPOPT_CIPSO option. */
1311 opt_len = (buf_len + 3) & ~3; 1312 opt_len = (buf_len + 3) & ~3;
1312 opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); 1313 opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
1313 if (opt == NULL) { 1314 if (opt == NULL) {
@@ -1317,11 +1318,9 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1317 memcpy(opt->__data, buf, buf_len); 1318 memcpy(opt->__data, buf, buf_len);
1318 opt->optlen = opt_len; 1319 opt->optlen = opt_len;
1319 opt->is_data = 1; 1320 opt->is_data = 1;
1321 opt->cipso = sizeof(struct iphdr);
1320 kfree(buf); 1322 kfree(buf);
1321 buf = NULL; 1323 buf = NULL;
1322 ret_val = ip_options_compile(opt, NULL);
1323 if (ret_val != 0)
1324 goto socket_setattr_failure;
1325 1324
1326 sk_inet = inet_sk(sk); 1325 sk_inet = inet_sk(sk);
1327 if (sk_inet->is_icsk) { 1326 if (sk_inet->is_icsk) {
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 8dabbfc31267..9f02917d6f45 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -443,7 +443,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
443 opt->router_alert = optptr - iph; 443 opt->router_alert = optptr - iph;
444 break; 444 break;
445 case IPOPT_CIPSO: 445 case IPOPT_CIPSO:
446 if (opt->cipso) { 446 if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) {
447 pp_ptr = optptr; 447 pp_ptr = optptr;
448 goto error; 448 goto error;
449 } 449 }
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 0849f1cced13..413c2d0a1f3d 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -466,7 +466,13 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i
466 return -EINVAL; 466 return -EINVAL;
467 } 467 }
468 468
469 if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset)
470 return -EINVAL;
471
469 t = arpt_get_target(e); 472 t = arpt_get_target(e);
473 if (e->target_offset + t->u.target_size > e->next_offset)
474 return -EINVAL;
475
470 target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, 476 target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name,
471 t->u.user.revision), 477 t->u.user.revision),
472 "arpt_%s", t->u.user.name); 478 "arpt_%s", t->u.user.name);
@@ -621,20 +627,18 @@ static int translate_table(const char *name,
621 } 627 }
622 } 628 }
623 629
624 if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
625 duprintf("Looping hook\n");
626 return -ELOOP;
627 }
628
629 /* Finally, each sanity check must pass */ 630 /* Finally, each sanity check must pass */
630 i = 0; 631 i = 0;
631 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, 632 ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,
632 check_entry, name, size, &i); 633 check_entry, name, size, &i);
633 634
634 if (ret != 0) { 635 if (ret != 0)
635 ARPT_ENTRY_ITERATE(entry0, newinfo->size, 636 goto cleanup;
636 cleanup_entry, &i); 637
637 return ret; 638 ret = -ELOOP;
639 if (!mark_source_chains(newinfo, valid_hooks, entry0)) {
640 duprintf("Looping hook\n");
641 goto cleanup;
638 } 642 }
639 643
640 /* And one copy for every other CPU */ 644 /* And one copy for every other CPU */
@@ -643,6 +647,9 @@ static int translate_table(const char *name,
643 memcpy(newinfo->entries[i], entry0, newinfo->size); 647 memcpy(newinfo->entries[i], entry0, newinfo->size);
644 } 648 }
645 649
650 return 0;
651cleanup:
652 ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
646 return ret; 653 return ret;
647} 654}
648 655
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 4b90927619b8..8a455439b128 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -547,12 +547,18 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size,
547 return -EINVAL; 547 return -EINVAL;
548 } 548 }
549 549
550 if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset)
551 return -EINVAL;
552
550 j = 0; 553 j = 0;
551 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j); 554 ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
552 if (ret != 0) 555 if (ret != 0)
553 goto cleanup_matches; 556 goto cleanup_matches;
554 557
555 t = ipt_get_target(e); 558 t = ipt_get_target(e);
559 ret = -EINVAL;
560 if (e->target_offset + t->u.target_size > e->next_offset)
561 goto cleanup_matches;
556 target = try_then_request_module(xt_find_target(AF_INET, 562 target = try_then_request_module(xt_find_target(AF_INET,
557 t->u.user.name, 563 t->u.user.name,
558 t->u.user.revision), 564 t->u.user.revision),
@@ -712,19 +718,17 @@ translate_table(const char *name,
712 } 718 }
713 } 719 }
714 720
715 if (!mark_source_chains(newinfo, valid_hooks, entry0))
716 return -ELOOP;
717
718 /* Finally, each sanity check must pass */ 721 /* Finally, each sanity check must pass */
719 i = 0; 722 i = 0;
720 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 723 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
721 check_entry, name, size, &i); 724 check_entry, name, size, &i);
722 725
723 if (ret != 0) { 726 if (ret != 0)
724 IPT_ENTRY_ITERATE(entry0, newinfo->size, 727 goto cleanup;
725 cleanup_entry, &i); 728
726 return ret; 729 ret = -ELOOP;
727 } 730 if (!mark_source_chains(newinfo, valid_hooks, entry0))
731 goto cleanup;
728 732
729 /* And one copy for every other CPU */ 733 /* And one copy for every other CPU */
730 for_each_possible_cpu(i) { 734 for_each_possible_cpu(i) {
@@ -732,6 +736,9 @@ translate_table(const char *name,
732 memcpy(newinfo->entries[i], entry0, newinfo->size); 736 memcpy(newinfo->entries[i], entry0, newinfo->size);
733 } 737 }
734 738
739 return 0;
740cleanup:
741 IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
735 return ret; 742 return ret;
736} 743}
737 744
@@ -1463,6 +1470,10 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
1463 return -EINVAL; 1470 return -EINVAL;
1464 } 1471 }
1465 1472
1473 if (e->target_offset + sizeof(struct compat_xt_entry_target) >
1474 e->next_offset)
1475 return -EINVAL;
1476
1466 off = 0; 1477 off = 0;
1467 entry_offset = (void *)e - (void *)base; 1478 entry_offset = (void *)e - (void *)base;
1468 j = 0; 1479 j = 0;
@@ -1472,6 +1483,9 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
1472 goto cleanup_matches; 1483 goto cleanup_matches;
1473 1484
1474 t = ipt_get_target(e); 1485 t = ipt_get_target(e);
1486 ret = -EINVAL;
1487 if (e->target_offset + t->u.target_size > e->next_offset)
1488 goto cleanup_matches;
1475 target = try_then_request_module(xt_find_target(AF_INET, 1489 target = try_then_request_module(xt_find_target(AF_INET,
1476 t->u.user.name, 1490 t->u.user.name,
1477 t->u.user.revision), 1491 t->u.user.revision),
@@ -1513,7 +1527,7 @@ cleanup_matches:
1513 1527
1514static inline int compat_copy_match_from_user(struct ipt_entry_match *m, 1528static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
1515 void **dstptr, compat_uint_t *size, const char *name, 1529 void **dstptr, compat_uint_t *size, const char *name,
1516 const struct ipt_ip *ip, unsigned int hookmask, int *i) 1530 const struct ipt_ip *ip, unsigned int hookmask)
1517{ 1531{
1518 struct ipt_entry_match *dm; 1532 struct ipt_entry_match *dm;
1519 struct ipt_match *match; 1533 struct ipt_match *match;
@@ -1526,22 +1540,13 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m,
1526 ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm), 1540 ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm),
1527 name, hookmask, ip->proto, 1541 name, hookmask, ip->proto,
1528 ip->invflags & IPT_INV_PROTO); 1542 ip->invflags & IPT_INV_PROTO);
1529 if (ret) 1543 if (!ret && m->u.kernel.match->checkentry
1530 goto err;
1531
1532 if (m->u.kernel.match->checkentry
1533 && !m->u.kernel.match->checkentry(name, ip, match, dm->data, 1544 && !m->u.kernel.match->checkentry(name, ip, match, dm->data,
1534 hookmask)) { 1545 hookmask)) {
1535 duprintf("ip_tables: check failed for `%s'.\n", 1546 duprintf("ip_tables: check failed for `%s'.\n",
1536 m->u.kernel.match->name); 1547 m->u.kernel.match->name);
1537 ret = -EINVAL; 1548 ret = -EINVAL;
1538 goto err;
1539 } 1549 }
1540 (*i)++;
1541 return 0;
1542
1543err:
1544 module_put(m->u.kernel.match->me);
1545 return ret; 1550 return ret;
1546} 1551}
1547 1552
@@ -1553,19 +1558,18 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1553 struct ipt_target *target; 1558 struct ipt_target *target;
1554 struct ipt_entry *de; 1559 struct ipt_entry *de;
1555 unsigned int origsize; 1560 unsigned int origsize;
1556 int ret, h, j; 1561 int ret, h;
1557 1562
1558 ret = 0; 1563 ret = 0;
1559 origsize = *size; 1564 origsize = *size;
1560 de = (struct ipt_entry *)*dstptr; 1565 de = (struct ipt_entry *)*dstptr;
1561 memcpy(de, e, sizeof(struct ipt_entry)); 1566 memcpy(de, e, sizeof(struct ipt_entry));
1562 1567
1563 j = 0;
1564 *dstptr += sizeof(struct compat_ipt_entry); 1568 *dstptr += sizeof(struct compat_ipt_entry);
1565 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size, 1569 ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size,
1566 name, &de->ip, de->comefrom, &j); 1570 name, &de->ip, de->comefrom);
1567 if (ret) 1571 if (ret)
1568 goto cleanup_matches; 1572 goto err;
1569 de->target_offset = e->target_offset - (origsize - *size); 1573 de->target_offset = e->target_offset - (origsize - *size);
1570 t = ipt_get_target(e); 1574 t = ipt_get_target(e);
1571 target = t->u.kernel.target; 1575 target = t->u.kernel.target;
@@ -1599,12 +1603,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1599 goto err; 1603 goto err;
1600 } 1604 }
1601 ret = 0; 1605 ret = 0;
1602 return ret;
1603
1604err: 1606err:
1605 module_put(t->u.kernel.target->me);
1606cleanup_matches:
1607 IPT_MATCH_ITERATE(e, cleanup_match, &j);
1608 return ret; 1607 return ret;
1609} 1608}
1610 1609
@@ -1618,7 +1617,7 @@ translate_compat_table(const char *name,
1618 unsigned int *hook_entries, 1617 unsigned int *hook_entries,
1619 unsigned int *underflows) 1618 unsigned int *underflows)
1620{ 1619{
1621 unsigned int i; 1620 unsigned int i, j;
1622 struct xt_table_info *newinfo, *info; 1621 struct xt_table_info *newinfo, *info;
1623 void *pos, *entry0, *entry1; 1622 void *pos, *entry0, *entry1;
1624 unsigned int size; 1623 unsigned int size;
@@ -1636,21 +1635,21 @@ translate_compat_table(const char *name,
1636 } 1635 }
1637 1636
1638 duprintf("translate_compat_table: size %u\n", info->size); 1637 duprintf("translate_compat_table: size %u\n", info->size);
1639 i = 0; 1638 j = 0;
1640 xt_compat_lock(AF_INET); 1639 xt_compat_lock(AF_INET);
1641 /* Walk through entries, checking offsets. */ 1640 /* Walk through entries, checking offsets. */
1642 ret = IPT_ENTRY_ITERATE(entry0, total_size, 1641 ret = IPT_ENTRY_ITERATE(entry0, total_size,
1643 check_compat_entry_size_and_hooks, 1642 check_compat_entry_size_and_hooks,
1644 info, &size, entry0, 1643 info, &size, entry0,
1645 entry0 + total_size, 1644 entry0 + total_size,
1646 hook_entries, underflows, &i, name); 1645 hook_entries, underflows, &j, name);
1647 if (ret != 0) 1646 if (ret != 0)
1648 goto out_unlock; 1647 goto out_unlock;
1649 1648
1650 ret = -EINVAL; 1649 ret = -EINVAL;
1651 if (i != number) { 1650 if (j != number) {
1652 duprintf("translate_compat_table: %u not %u entries\n", 1651 duprintf("translate_compat_table: %u not %u entries\n",
1653 i, number); 1652 j, number);
1654 goto out_unlock; 1653 goto out_unlock;
1655 } 1654 }
1656 1655
@@ -1709,8 +1708,10 @@ translate_compat_table(const char *name,
1709free_newinfo: 1708free_newinfo:
1710 xt_free_table_info(newinfo); 1709 xt_free_table_info(newinfo);
1711out: 1710out:
1711 IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j);
1712 return ret; 1712 return ret;
1713out_unlock: 1713out_unlock:
1714 compat_flush_offsets();
1714 xt_compat_unlock(AF_INET); 1715 xt_compat_unlock(AF_INET);
1715 goto out; 1716 goto out;
1716} 1717}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index b430cf2a4f66..5c31dead2bdc 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -329,7 +329,7 @@ error:
329 return err; 329 return err;
330} 330}
331 331
332static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 332static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
333{ 333{
334 struct iovec *iov; 334 struct iovec *iov;
335 u8 __user *type = NULL; 335 u8 __user *type = NULL;
@@ -338,7 +338,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
338 unsigned int i; 338 unsigned int i;
339 339
340 if (!msg->msg_iov) 340 if (!msg->msg_iov)
341 return; 341 return 0;
342 342
343 for (i = 0; i < msg->msg_iovlen; i++) { 343 for (i = 0; i < msg->msg_iovlen; i++) {
344 iov = &msg->msg_iov[i]; 344 iov = &msg->msg_iov[i];
@@ -360,8 +360,9 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
360 code = iov->iov_base; 360 code = iov->iov_base;
361 361
362 if (type && code) { 362 if (type && code) {
363 get_user(fl->fl_icmp_type, type); 363 if (get_user(fl->fl_icmp_type, type) ||
364 get_user(fl->fl_icmp_code, code); 364 get_user(fl->fl_icmp_code, code))
365 return -EFAULT;
365 probed = 1; 366 probed = 1;
366 } 367 }
367 break; 368 break;
@@ -372,6 +373,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
372 if (probed) 373 if (probed)
373 break; 374 break;
374 } 375 }
376 return 0;
375} 377}
376 378
377static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 379static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
@@ -480,8 +482,11 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
480 .proto = inet->hdrincl ? IPPROTO_RAW : 482 .proto = inet->hdrincl ? IPPROTO_RAW :
481 sk->sk_protocol, 483 sk->sk_protocol,
482 }; 484 };
483 if (!inet->hdrincl) 485 if (!inet->hdrincl) {
484 raw_probe_proto_opt(&fl, msg); 486 err = raw_probe_proto_opt(&fl, msg);
487 if (err)
488 goto done;
489 }
485 490
486 security_sk_classify_flow(sk, &fl); 491 security_sk_classify_flow(sk, &fl);
487 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); 492 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1d672b0547f2..6d4533b58dca 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -330,8 +330,10 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
330 fl->share = freq->flr_share; 330 fl->share = freq->flr_share;
331 addr_type = ipv6_addr_type(&freq->flr_dst); 331 addr_type = ipv6_addr_type(&freq->flr_dst);
332 if ((addr_type&IPV6_ADDR_MAPPED) 332 if ((addr_type&IPV6_ADDR_MAPPED)
333 || addr_type == IPV6_ADDR_ANY) 333 || addr_type == IPV6_ADDR_ANY) {
334 err = -EINVAL;
334 goto done; 335 goto done;
336 }
335 ipv6_addr_copy(&fl->dst, &freq->flr_dst); 337 ipv6_addr_copy(&fl->dst, &freq->flr_dst);
336 atomic_set(&fl->users, 1); 338 atomic_set(&fl->users, 1);
337 switch (fl->share) { 339 switch (fl->share) {
@@ -587,6 +589,8 @@ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flo
587 while (!fl) { 589 while (!fl) {
588 if (++state->bucket <= FL_HASH_MASK) 590 if (++state->bucket <= FL_HASH_MASK)
589 fl = fl_ht[state->bucket]; 591 fl = fl_ht[state->bucket];
592 else
593 break;
590 } 594 }
591 return fl; 595 return fl;
592} 596}
@@ -623,9 +627,13 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
623 read_unlock_bh(&ip6_fl_lock); 627 read_unlock_bh(&ip6_fl_lock);
624} 628}
625 629
626static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) 630static int ip6fl_seq_show(struct seq_file *seq, void *v)
627{ 631{
628 while(fl) { 632 if (v == SEQ_START_TOKEN)
633 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
634 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
635 else {
636 struct ip6_flowlabel *fl = v;
629 seq_printf(seq, 637 seq_printf(seq,
630 "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n", 638 "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n",
631 (unsigned)ntohl(fl->label), 639 (unsigned)ntohl(fl->label),
@@ -636,17 +644,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
636 (long)(fl->expires - jiffies)/HZ, 644 (long)(fl->expires - jiffies)/HZ,
637 NIP6(fl->dst), 645 NIP6(fl->dst),
638 fl->opt ? fl->opt->opt_nflen : 0); 646 fl->opt ? fl->opt->opt_nflen : 0);
639 fl = fl->next;
640 } 647 }
641}
642
643static int ip6fl_seq_show(struct seq_file *seq, void *v)
644{
645 if (v == SEQ_START_TOKEN)
646 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
647 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
648 else
649 ip6fl_fl_seq_show(seq, v);
650 return 0; 648 return 0;
651} 649}
652 650
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 4bc4e5b33794..d7c45a9c15fe 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -40,7 +40,7 @@ config IP6_NF_QUEUE
40 To compile it as a module, choose M here. If unsure, say N. 40 To compile it as a module, choose M here. If unsure, say N.
41 41
42config IP6_NF_IPTABLES 42config IP6_NF_IPTABLES
43 tristate "IP6 tables support (required for filtering/masq/NAT)" 43 tristate "IP6 tables support (required for filtering)"
44 depends on NETFILTER_XTABLES 44 depends on NETFILTER_XTABLES
45 help 45 help
46 ip6tables is a general, extensible packet identification framework. 46 ip6tables is a general, extensible packet identification framework.
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 53bf977cca63..167c2ea88f6b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -586,12 +586,19 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
586 return -EINVAL; 586 return -EINVAL;
587 } 587 }
588 588
589 if (e->target_offset + sizeof(struct ip6t_entry_target) >
590 e->next_offset)
591 return -EINVAL;
592
589 j = 0; 593 j = 0;
590 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j); 594 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
591 if (ret != 0) 595 if (ret != 0)
592 goto cleanup_matches; 596 goto cleanup_matches;
593 597
594 t = ip6t_get_target(e); 598 t = ip6t_get_target(e);
599 ret = -EINVAL;
600 if (e->target_offset + t->u.target_size > e->next_offset)
601 goto cleanup_matches;
595 target = try_then_request_module(xt_find_target(AF_INET6, 602 target = try_then_request_module(xt_find_target(AF_INET6,
596 t->u.user.name, 603 t->u.user.name,
597 t->u.user.revision), 604 t->u.user.revision),
@@ -751,19 +758,17 @@ translate_table(const char *name,
751 } 758 }
752 } 759 }
753 760
754 if (!mark_source_chains(newinfo, valid_hooks, entry0))
755 return -ELOOP;
756
757 /* Finally, each sanity check must pass */ 761 /* Finally, each sanity check must pass */
758 i = 0; 762 i = 0;
759 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 763 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
760 check_entry, name, size, &i); 764 check_entry, name, size, &i);
761 765
762 if (ret != 0) { 766 if (ret != 0)
763 IP6T_ENTRY_ITERATE(entry0, newinfo->size, 767 goto cleanup;
764 cleanup_entry, &i); 768
765 return ret; 769 ret = -ELOOP;
766 } 770 if (!mark_source_chains(newinfo, valid_hooks, entry0))
771 goto cleanup;
767 772
768 /* And one copy for every other CPU */ 773 /* And one copy for every other CPU */
769 for_each_possible_cpu(i) { 774 for_each_possible_cpu(i) {
@@ -771,6 +776,9 @@ translate_table(const char *name,
771 memcpy(newinfo->entries[i], entry0, newinfo->size); 776 memcpy(newinfo->entries[i], entry0, newinfo->size);
772 } 777 }
773 778
779 return 0;
780cleanup:
781 IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
774 return ret; 782 return ret;
775} 783}
776 784
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d09329ca3267..d6dedc4aec77 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -604,7 +604,7 @@ error:
604 return err; 604 return err;
605} 605}
606 606
607static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 607static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
608{ 608{
609 struct iovec *iov; 609 struct iovec *iov;
610 u8 __user *type = NULL; 610 u8 __user *type = NULL;
@@ -616,7 +616,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
616 int i; 616 int i;
617 617
618 if (!msg->msg_iov) 618 if (!msg->msg_iov)
619 return; 619 return 0;
620 620
621 for (i = 0; i < msg->msg_iovlen; i++) { 621 for (i = 0; i < msg->msg_iovlen; i++) {
622 iov = &msg->msg_iov[i]; 622 iov = &msg->msg_iov[i];
@@ -638,8 +638,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
638 code = iov->iov_base; 638 code = iov->iov_base;
639 639
640 if (type && code) { 640 if (type && code) {
641 get_user(fl->fl_icmp_type, type); 641 if (get_user(fl->fl_icmp_type, type) ||
642 get_user(fl->fl_icmp_code, code); 642 get_user(fl->fl_icmp_code, code))
643 return -EFAULT;
643 probed = 1; 644 probed = 1;
644 } 645 }
645 break; 646 break;
@@ -650,7 +651,8 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
650 /* check if type field is readable or not. */ 651 /* check if type field is readable or not. */
651 if (iov->iov_len > 2 - len) { 652 if (iov->iov_len > 2 - len) {
652 u8 __user *p = iov->iov_base; 653 u8 __user *p = iov->iov_base;
653 get_user(fl->fl_mh_type, &p[2 - len]); 654 if (get_user(fl->fl_mh_type, &p[2 - len]))
655 return -EFAULT;
654 probed = 1; 656 probed = 1;
655 } else 657 } else
656 len += iov->iov_len; 658 len += iov->iov_len;
@@ -664,6 +666,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
664 if (probed) 666 if (probed)
665 break; 667 break;
666 } 668 }
669 return 0;
667} 670}
668 671
669static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, 672static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
@@ -787,7 +790,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
787 opt = ipv6_fixup_options(&opt_space, opt); 790 opt = ipv6_fixup_options(&opt_space, opt);
788 791
789 fl.proto = proto; 792 fl.proto = proto;
790 rawv6_probe_proto_opt(&fl, msg); 793 err = rawv6_probe_proto_opt(&fl, msg);
794 if (err)
795 goto out;
791 796
792 ipv6_addr_copy(&fl.fl6_dst, daddr); 797 ipv6_addr_copy(&fl.fl6_dst, daddr);
793 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 798 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 093b3ddc513c..836541e509fe 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1520,9 +1520,10 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
1520 if (iter(ct, data)) 1520 if (iter(ct, data))
1521 goto found; 1521 goto found;
1522 } 1522 }
1523 write_unlock_bh(&nf_conntrack_lock);
1523 return NULL; 1524 return NULL;
1524found: 1525found:
1525 atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); 1526 atomic_inc(&ct->ct_general.use);
1526 write_unlock_bh(&nf_conntrack_lock); 1527 write_unlock_bh(&nf_conntrack_lock);
1527 return ct; 1528 return ct;
1528} 1529}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d56e0d21f919..d527c8977b1f 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1075,8 +1075,9 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
1075 return -EINVAL; 1075 return -EINVAL;
1076 len = sizeof(int); 1076 len = sizeof(int);
1077 val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0; 1077 val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0;
1078 put_user(len, optlen); 1078 if (put_user(len, optlen) ||
1079 put_user(val, optval); 1079 put_user(val, optval))
1080 return -EFAULT;
1080 err = 0; 1081 err = 0;
1081 break; 1082 break;
1082 default: 1083 default:
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 27329ce9c311..ed0445fe85e7 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -346,11 +346,18 @@ void sctp_association_free(struct sctp_association *asoc)
346 struct list_head *pos, *temp; 346 struct list_head *pos, *temp;
347 int i; 347 int i;
348 348
349 list_del(&asoc->asocs); 349 /* Only real associations count against the endpoint, so
350 * don't bother for if this is a temporary association.
351 */
352 if (!asoc->temp) {
353 list_del(&asoc->asocs);
350 354
351 /* Decrement the backlog value for a TCP-style listening socket. */ 355 /* Decrement the backlog value for a TCP-style listening
352 if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) 356 * socket.
353 sk->sk_ack_backlog--; 357 */
358 if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
359 sk->sk_ack_backlog--;
360 }
354 361
355 /* Mark as dead, so other users can know this structure is 362 /* Mark as dead, so other users can know this structure is
356 * going away. 363 * going away.
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 35c49ff2d062..9b6b394b66f6 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -144,6 +144,13 @@ void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
144{ 144{
145 struct sock *sk = ep->base.sk; 145 struct sock *sk = ep->base.sk;
146 146
147 /* If this is a temporary association, don't bother
148 * since we'll be removing it shortly and don't
149 * want anyone to find it anyway.
150 */
151 if (asoc->temp)
152 return;
153
147 /* Now just add it to our list of asocs */ 154 /* Now just add it to our list of asocs */
148 list_add_tail(&asoc->asocs, &ep->asocs); 155 list_add_tail(&asoc->asocs, &ep->asocs);
149 156
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 64f630102532..6d82f400d13c 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -135,6 +135,9 @@ int sctp_rcv(struct sk_buff *skb)
135 135
136 SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS); 136 SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS);
137 137
138 if (skb_linearize(skb))
139 goto discard_it;
140
138 sh = (struct sctphdr *) skb->h.raw; 141 sh = (struct sctphdr *) skb->h.raw;
139 142
140 /* Pull up the IP and SCTP headers. */ 143 /* Pull up the IP and SCTP headers. */
@@ -768,6 +771,9 @@ static void __sctp_hash_established(struct sctp_association *asoc)
768/* Add an association to the hash. Local BH-safe. */ 771/* Add an association to the hash. Local BH-safe. */
769void sctp_hash_established(struct sctp_association *asoc) 772void sctp_hash_established(struct sctp_association *asoc)
770{ 773{
774 if (asoc->temp)
775 return;
776
771 sctp_local_bh_disable(); 777 sctp_local_bh_disable();
772 __sctp_hash_established(asoc); 778 __sctp_hash_established(asoc);
773 sctp_local_bh_enable(); 779 sctp_local_bh_enable();
@@ -801,6 +807,9 @@ static void __sctp_unhash_established(struct sctp_association *asoc)
801/* Remove association from the hash table. Local BH-safe. */ 807/* Remove association from the hash table. Local BH-safe. */
802void sctp_unhash_established(struct sctp_association *asoc) 808void sctp_unhash_established(struct sctp_association *asoc)
803{ 809{
810 if (asoc->temp)
811 return;
812
804 sctp_local_bh_disable(); 813 sctp_local_bh_disable();
805 __sctp_unhash_established(asoc); 814 __sctp_unhash_established(asoc);
806 sctp_local_bh_enable(); 815 sctp_local_bh_enable();
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index fac7674438a4..5b4f82fd98f8 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -591,7 +591,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
591 newinet->dport = htons(asoc->peer.port); 591 newinet->dport = htons(asoc->peer.port);
592 newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; 592 newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
593 newinet->pmtudisc = inet->pmtudisc; 593 newinet->pmtudisc = inet->pmtudisc;
594 newinet->id = 0; 594 newinet->id = asoc->next_tsn ^ jiffies;
595 595
596 newinet->uc_ttl = -1; 596 newinet->uc_ttl = -1;
597 newinet->mc_loop = 1; 597 newinet->mc_loop = 1;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 9f34dec6ff8e..935bc9187fd8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3372,6 +3372,7 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
3372{ 3372{
3373 struct sock *sk = asoc->base.sk; 3373 struct sock *sk = asoc->base.sk;
3374 struct socket *sock; 3374 struct socket *sock;
3375 struct inet_sock *inetsk;
3375 int err = 0; 3376 int err = 0;
3376 3377
3377 /* An association cannot be branched off from an already peeled-off 3378 /* An association cannot be branched off from an already peeled-off
@@ -3389,6 +3390,14 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
3389 * asoc to the newsk. 3390 * asoc to the newsk.
3390 */ 3391 */
3391 sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); 3392 sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
3393
3394 /* Make peeled-off sockets more like 1-1 accepted sockets.
3395 * Set the daddr and initialize id to something more random
3396 */
3397 inetsk = inet_sk(sock->sk);
3398 inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
3399 inetsk->id = asoc->next_tsn ^ jiffies;
3400
3392 *sockp = sock; 3401 *sockp = sock;
3393 3402
3394 return err; 3403 return err;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 2b2e59d8ffbc..b43e7647e125 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -323,7 +323,7 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
323 x->props.replay_window = p->replay_window; 323 x->props.replay_window = p->replay_window;
324 x->props.reqid = p->reqid; 324 x->props.reqid = p->reqid;
325 x->props.family = p->family; 325 x->props.family = p->family;
326 x->props.saddr = p->saddr; 326 memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
327 x->props.flags = p->flags; 327 x->props.flags = p->flags;
328} 328}
329 329
@@ -545,7 +545,7 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
545 memcpy(&p->lft, &x->lft, sizeof(p->lft)); 545 memcpy(&p->lft, &x->lft, sizeof(p->lft));
546 memcpy(&p->curlft, &x->curlft, sizeof(p->curlft)); 546 memcpy(&p->curlft, &x->curlft, sizeof(p->curlft));
547 memcpy(&p->stats, &x->stats, sizeof(p->stats)); 547 memcpy(&p->stats, &x->stats, sizeof(p->stats));
548 p->saddr = x->props.saddr; 548 memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr));
549 p->mode = x->props.mode; 549 p->mode = x->props.mode;
550 p->replay_window = x->props.replay_window; 550 p->replay_window = x->props.replay_window;
551 p->reqid = x->props.reqid; 551 p->reqid = x->props.reqid;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e9969a2fc846..8ab5679a37a3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3313,7 +3313,13 @@ static int selinux_socket_getpeername(struct socket *sock)
3313 3313
3314static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) 3314static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3315{ 3315{
3316 return socket_has_perm(current, sock, SOCKET__SETOPT); 3316 int err;
3317
3318 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3319 if (err)
3320 return err;
3321
3322 return selinux_netlbl_socket_setsockopt(sock, level, optname);
3317} 3323}
3318 3324
3319static int selinux_socket_getsockopt(struct socket *sock, int level, 3325static int selinux_socket_getsockopt(struct socket *sock, int level,
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h
index ecab4bddaaf4..9de10cc2cef2 100644
--- a/security/selinux/include/selinux_netlabel.h
+++ b/security/selinux/include/selinux_netlabel.h
@@ -53,6 +53,9 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
53void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, 53void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
54 struct sk_security_struct *newssec); 54 struct sk_security_struct *newssec);
55int selinux_netlbl_inode_permission(struct inode *inode, int mask); 55int selinux_netlbl_inode_permission(struct inode *inode, int mask);
56int selinux_netlbl_socket_setsockopt(struct socket *sock,
57 int level,
58 int optname);
56#else 59#else
57static inline void selinux_netlbl_cache_invalidate(void) 60static inline void selinux_netlbl_cache_invalidate(void)
58{ 61{
@@ -114,6 +117,13 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode,
114{ 117{
115 return 0; 118 return 0;
116} 119}
120
121static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
122 int level,
123 int optname)
124{
125 return 0;
126}
117#endif /* CONFIG_NETLABEL */ 127#endif /* CONFIG_NETLABEL */
118 128
119#endif 129#endif
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b1f6fb36c699..bfe122764c98 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2682,4 +2682,41 @@ u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2682 2682
2683 return peer_sid; 2683 return peer_sid;
2684} 2684}
2685
2686/**
2687 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
2688 * @sock: the socket
2689 * @level: the socket level or protocol
2690 * @optname: the socket option name
2691 *
2692 * Description:
2693 * Check the setsockopt() call and if the user is trying to replace the IP
2694 * options on a socket and a NetLabel is in place for the socket deny the
2695 * access; otherwise allow the access. Returns zero when the access is
2696 * allowed, -EACCES when denied, and other negative values on error.
2697 *
2698 */
2699int selinux_netlbl_socket_setsockopt(struct socket *sock,
2700 int level,
2701 int optname)
2702{
2703 int rc = 0;
2704 struct inode *inode = SOCK_INODE(sock);
2705 struct sk_security_struct *sksec = sock->sk->sk_security;
2706 struct inode_security_struct *isec = inode->i_security;
2707 struct netlbl_lsm_secattr secattr;
2708
2709 mutex_lock(&isec->lock);
2710 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
2711 sksec->nlbl_state == NLBL_LABELED) {
2712 netlbl_secattr_init(&secattr);
2713 rc = netlbl_socket_getattr(sock, &secattr);
2714 if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld))
2715 rc = -EACCES;
2716 netlbl_secattr_destroy(&secattr);
2717 }
2718 mutex_unlock(&isec->lock);
2719
2720 return rc;
2721}
2685#endif /* CONFIG_NETLABEL */ 2722#endif /* CONFIG_NETLABEL */