]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Dec 2012 21:00:47 +0000 (13:00 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Dec 2012 21:00:47 +0000 (13:00 -0800)
added patches:
bonding-bonding-driver-does-not-consider-the-gso_max_size-gso_max_segs-setting-of-slave-devices.patch
bonding-fix-race-condition-in-bonding_store_slaves_active.patch
inet_diag-avoid-unsafe-and-nonsensical-prefix-matches-in-inet_diag_bc_run.patch
inet_diag-fix-oops-for-ipv4-af_inet6-tcp-syn-recv-state.patch
inet_diag-validate-byte-code-to-prevent-oops-in-inet_diag_bc_run.patch
inet_diag-validate-port-comparison-byte-code-to-prevent-unsafe-reads.patch
ipv4-ip_check_defrag-must-not-modify-skb-before-unsharing.patch
irda-sir_dev-fix-copy-paste-typo.patch
ne2000-add-the-right-platform-device.patch
sctp-fix-enomem-result-with-invalid-user-space-pointer-in-sendto-syscall.patch
sctp-fix-memory-leak-in-sctp_datamsg_from_user-when-copy-from-user-space-fails.patch
usb-ipheth-add-iphone-5-support.patch

13 files changed:
queue-3.4/bonding-bonding-driver-does-not-consider-the-gso_max_size-gso_max_segs-setting-of-slave-devices.patch [new file with mode: 0644]
queue-3.4/bonding-fix-race-condition-in-bonding_store_slaves_active.patch [new file with mode: 0644]
queue-3.4/inet_diag-avoid-unsafe-and-nonsensical-prefix-matches-in-inet_diag_bc_run.patch [new file with mode: 0644]
queue-3.4/inet_diag-fix-oops-for-ipv4-af_inet6-tcp-syn-recv-state.patch [new file with mode: 0644]
queue-3.4/inet_diag-validate-byte-code-to-prevent-oops-in-inet_diag_bc_run.patch [new file with mode: 0644]
queue-3.4/inet_diag-validate-port-comparison-byte-code-to-prevent-unsafe-reads.patch [new file with mode: 0644]
queue-3.4/ipv4-ip_check_defrag-must-not-modify-skb-before-unsharing.patch [new file with mode: 0644]
queue-3.4/irda-sir_dev-fix-copy-paste-typo.patch [new file with mode: 0644]
queue-3.4/ne2000-add-the-right-platform-device.patch [new file with mode: 0644]
queue-3.4/sctp-fix-enomem-result-with-invalid-user-space-pointer-in-sendto-syscall.patch [new file with mode: 0644]
queue-3.4/sctp-fix-memory-leak-in-sctp_datamsg_from_user-when-copy-from-user-space-fails.patch [new file with mode: 0644]
queue-3.4/series [new file with mode: 0644]
queue-3.4/usb-ipheth-add-iphone-5-support.patch [new file with mode: 0644]

diff --git a/queue-3.4/bonding-bonding-driver-does-not-consider-the-gso_max_size-gso_max_segs-setting-of-slave-devices.patch b/queue-3.4/bonding-bonding-driver-does-not-consider-the-gso_max_size-gso_max_segs-setting-of-slave-devices.patch
new file mode 100644 (file)
index 0000000..e7d3dde
--- /dev/null
@@ -0,0 +1,48 @@
+From b680f523aeb9d6f79355e15b531b1af09570dee4 Mon Sep 17 00:00:00 2001
+From: Sarveshwar Bandi <sarveshwar.bandi@emulex.com>
+Date: Wed, 21 Nov 2012 04:35:03 +0000
+Subject: bonding: Bonding driver does not consider the gso_max_size/gso_max_segs setting of slave devices.
+
+
+From: Sarveshwar Bandi <sarveshwar.bandi@emulex.com>
+
+[ Upstream commit 0e376bd0b791ac6ac6bdb051492df0769c840848 ]
+
+Patch sets the lowest gso_max_size and gso_max_segs values of the slave devices during enslave and detach.
+
+Signed-off-by: Sarveshwar Bandi <sarveshwar.bandi@emulex.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/bonding/bond_main.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1383,6 +1383,8 @@ static void bond_compute_features(struct
+       struct net_device *bond_dev = bond->dev;
+       netdev_features_t vlan_features = BOND_VLAN_FEATURES;
+       unsigned short max_hard_header_len = ETH_HLEN;
++      unsigned int gso_max_size = GSO_MAX_SIZE;
++      u16 gso_max_segs = GSO_MAX_SEGS;
+       int i;
+       read_lock(&bond->lock);
+@@ -1396,11 +1398,16 @@ static void bond_compute_features(struct
+               if (slave->dev->hard_header_len > max_hard_header_len)
+                       max_hard_header_len = slave->dev->hard_header_len;
++
++              gso_max_size = min(gso_max_size, slave->dev->gso_max_size);
++              gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs);
+       }
+ done:
+       bond_dev->vlan_features = vlan_features;
+       bond_dev->hard_header_len = max_hard_header_len;
++      bond_dev->gso_max_segs = gso_max_segs;
++      netif_set_gso_max_size(bond_dev, gso_max_size);
+       read_unlock(&bond->lock);
diff --git a/queue-3.4/bonding-fix-race-condition-in-bonding_store_slaves_active.patch b/queue-3.4/bonding-fix-race-condition-in-bonding_store_slaves_active.patch
new file mode 100644 (file)
index 0000000..fa7fe24
--- /dev/null
@@ -0,0 +1,44 @@
+From b9be04947edf4c74a81ae9040e33a624d66620d3 Mon Sep 17 00:00:00 2001
+From: "nikolay@redhat.com" <nikolay@redhat.com>
+Date: Thu, 29 Nov 2012 01:37:59 +0000
+Subject: bonding: fix race condition in bonding_store_slaves_active
+
+
+From: "nikolay@redhat.com" <nikolay@redhat.com>
+
+[ Upstream commit e196c0e579902f42cf72414461fb034e5a1ffbf7 ]
+
+Race between bonding_store_slaves_active() and slave manipulation
+ functions. The bond_for_each_slave use in bonding_store_slaves_active()
+ is not protected by any synchronization mechanism.
+ NULL pointer dereference is easy to reach.
+ Fixed by acquiring the bond->lock for the slave walk.
+
+ v2: Make description text < 75 columns
+
+Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
+Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/bonding/bond_sysfs.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/bonding/bond_sysfs.c
++++ b/drivers/net/bonding/bond_sysfs.c
+@@ -1578,6 +1578,7 @@ static ssize_t bonding_store_slaves_acti
+               goto out;
+       }
++      read_lock(&bond->lock);
+       bond_for_each_slave(bond, slave, i) {
+               if (!bond_is_active_slave(slave)) {
+                       if (new_value)
+@@ -1586,6 +1587,7 @@ static ssize_t bonding_store_slaves_acti
+                               slave->inactive = 1;
+               }
+       }
++      read_unlock(&bond->lock);
+ out:
+       return ret;
+ }
diff --git a/queue-3.4/inet_diag-avoid-unsafe-and-nonsensical-prefix-matches-in-inet_diag_bc_run.patch b/queue-3.4/inet_diag-avoid-unsafe-and-nonsensical-prefix-matches-in-inet_diag_bc_run.patch
new file mode 100644 (file)
index 0000000..4c6d213
--- /dev/null
@@ -0,0 +1,81 @@
+From a81faa0202b4a6bd474f64aecc83d52506690981 Mon Sep 17 00:00:00 2001
+From: Neal Cardwell <ncardwell@google.com>
+Date: Sat, 8 Dec 2012 19:43:23 +0000
+Subject: inet_diag: avoid unsafe and nonsensical prefix matches in inet_diag_bc_run()
+
+
+From: Neal Cardwell <ncardwell@google.com>
+
+[ Upstream commit f67caec9068cee426ec23cf9005a1dee2ecad187 ]
+
+Add logic to check the address family of the user-supplied conditional
+and the address family of the connection entry. We now do not do
+prefix matching of addresses from different address families (AF_INET
+vs AF_INET6), except for the previously existing support for having an
+IPv4 prefix match an IPv4-mapped IPv6 address (which this commit
+maintains as-is).
+
+This change is needed for two reasons:
+
+(1) The addresses are different lengths, so comparing a 128-bit IPv6
+prefix match condition to a 32-bit IPv4 connection address can cause
+us to unwittingly walk off the end of the IPv4 address and read
+garbage or oops.
+
+(2) The IPv4 and IPv6 address spaces are semantically distinct, so a
+simple bit-wise comparison of the prefixes is not meaningful, and
+would lead to bogus results (except for the IPv4-mapped IPv6 case,
+which this commit maintains).
+
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/inet_diag.c |   28 +++++++++++++++++-----------
+ 1 file changed, 17 insertions(+), 11 deletions(-)
+
+--- a/net/ipv4/inet_diag.c
++++ b/net/ipv4/inet_diag.c
+@@ -423,25 +423,31 @@ static int inet_diag_bc_run(const struct
+                               break;
+                       }
+-                      if (cond->prefix_len == 0)
+-                              break;
+-
+                       if (op->code == INET_DIAG_BC_S_COND)
+                               addr = entry->saddr;
+                       else
+                               addr = entry->daddr;
++                      if (cond->family != AF_UNSPEC &&
++                          cond->family != entry->family) {
++                              if (entry->family == AF_INET6 &&
++                                  cond->family == AF_INET) {
++                                      if (addr[0] == 0 && addr[1] == 0 &&
++                                          addr[2] == htonl(0xffff) &&
++                                          bitstring_match(addr + 3,
++                                                          cond->addr,
++                                                          cond->prefix_len))
++                                              break;
++                              }
++                              yes = 0;
++                              break;
++                      }
++
++                      if (cond->prefix_len == 0)
++                              break;
+                       if (bitstring_match(addr, cond->addr,
+                                           cond->prefix_len))
+                               break;
+-                      if (entry->family == AF_INET6 &&
+-                          cond->family == AF_INET) {
+-                              if (addr[0] == 0 && addr[1] == 0 &&
+-                                  addr[2] == htonl(0xffff) &&
+-                                  bitstring_match(addr + 3, cond->addr,
+-                                                  cond->prefix_len))
+-                                      break;
+-                      }
+                       yes = 0;
+                       break;
+               }
diff --git a/queue-3.4/inet_diag-fix-oops-for-ipv4-af_inet6-tcp-syn-recv-state.patch b/queue-3.4/inet_diag-fix-oops-for-ipv4-af_inet6-tcp-syn-recv-state.patch
new file mode 100644 (file)
index 0000000..7824345
--- /dev/null
@@ -0,0 +1,113 @@
+From 860f3ff2f6cb1f393c6dbae13bf7f333f4854156 Mon Sep 17 00:00:00 2001
+From: Neal Cardwell <ncardwell@google.com>
+Date: Sat, 8 Dec 2012 19:43:21 +0000
+Subject: inet_diag: fix oops for IPv4 AF_INET6 TCP SYN-RECV state
+
+
+From: Neal Cardwell <ncardwell@google.com>
+
+[ Upstream commit 1c95df85ca49640576de2f0a850925957b547b84 ]
+
+Fix inet_diag to be aware of the fact that AF_INET6 TCP connections
+instantiated for IPv4 traffic and in the SYN-RECV state were actually
+created with inet_reqsk_alloc(), instead of inet6_reqsk_alloc(). This
+means that for such connections inet6_rsk(req) returns a pointer to a
+random spot in memory up to roughly 64KB beyond the end of the
+request_sock.
+
+With this bug, for a server using AF_INET6 TCP sockets and serving
+IPv4 traffic, an inet_diag user like `ss state SYN-RECV` would lead to
+inet_diag_fill_req() causing an oops or the export to user space of 16
+bytes of kernel memory as a garbage IPv6 address, depending on where
+the garbage inet6_rsk(req) pointed.
+
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/inet_diag.c |   53 +++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 39 insertions(+), 14 deletions(-)
+
+--- a/net/ipv4/inet_diag.c
++++ b/net/ipv4/inet_diag.c
+@@ -44,6 +44,10 @@ struct inet_diag_entry {
+       u16 dport;
+       u16 family;
+       u16 userlocks;
++#if IS_ENABLED(CONFIG_IPV6)
++      struct in6_addr saddr_storage;  /* for IPv4-mapped-IPv6 addresses */
++      struct in6_addr daddr_storage;  /* for IPv4-mapped-IPv6 addresses */
++#endif
+ };
+ #define INET_DIAG_PUT(skb, attrtype, attrlen) \
+@@ -586,6 +590,36 @@ static int inet_twsk_diag_dump(struct in
+                                  cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
+ }
++/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses
++ * from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6.
++ */
++static inline void inet_diag_req_addrs(const struct sock *sk,
++                                     const struct request_sock *req,
++                                     struct inet_diag_entry *entry)
++{
++      struct inet_request_sock *ireq = inet_rsk(req);
++
++#if IS_ENABLED(CONFIG_IPV6)
++      if (sk->sk_family == AF_INET6) {
++              if (req->rsk_ops->family == AF_INET6) {
++                      entry->saddr = inet6_rsk(req)->loc_addr.s6_addr32;
++                      entry->daddr = inet6_rsk(req)->rmt_addr.s6_addr32;
++              } else if (req->rsk_ops->family == AF_INET) {
++                      ipv6_addr_set_v4mapped(ireq->loc_addr,
++                                             &entry->saddr_storage);
++                      ipv6_addr_set_v4mapped(ireq->rmt_addr,
++                                             &entry->daddr_storage);
++                      entry->saddr = entry->saddr_storage.s6_addr32;
++                      entry->daddr = entry->daddr_storage.s6_addr32;
++              }
++      } else
++#endif
++      {
++              entry->saddr = &ireq->loc_addr;
++              entry->daddr = &ireq->rmt_addr;
++      }
++}
++
+ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
+                             struct request_sock *req, u32 pid, u32 seq,
+                             const struct nlmsghdr *unlh)
+@@ -624,8 +658,10 @@ static int inet_diag_fill_req(struct sk_
+       r->idiag_inode = 0;
+ #if IS_ENABLED(CONFIG_IPV6)
+       if (r->idiag_family == AF_INET6) {
+-              *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr;
+-              *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr;
++              struct inet_diag_entry entry;
++              inet_diag_req_addrs(sk, req, &entry);
++              memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr));
++              memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr));
+       }
+ #endif
+       nlh->nlmsg_len = skb_tail_pointer(skb) - b;
+@@ -683,18 +719,7 @@ static int inet_diag_dump_reqs(struct sk
+                               continue;
+                       if (bc) {
+-                              entry.saddr =
+-#if IS_ENABLED(CONFIG_IPV6)
+-                                      (entry.family == AF_INET6) ?
+-                                      inet6_rsk(req)->loc_addr.s6_addr32 :
+-#endif
+-                                      &ireq->loc_addr;
+-                              entry.daddr =
+-#if IS_ENABLED(CONFIG_IPV6)
+-                                      (entry.family == AF_INET6) ?
+-                                      inet6_rsk(req)->rmt_addr.s6_addr32 :
+-#endif
+-                                      &ireq->rmt_addr;
++                              inet_diag_req_addrs(sk, req, &entry);
+                               entry.dport = ntohs(ireq->rmt_port);
+                               if (!inet_diag_bc_run(bc, &entry))
diff --git a/queue-3.4/inet_diag-validate-byte-code-to-prevent-oops-in-inet_diag_bc_run.patch b/queue-3.4/inet_diag-validate-byte-code-to-prevent-oops-in-inet_diag_bc_run.patch
new file mode 100644 (file)
index 0000000..d0a40c4
--- /dev/null
@@ -0,0 +1,110 @@
+From b834907c7c553dc02358417a535b8b486f481bd6 Mon Sep 17 00:00:00 2001
+From: Neal Cardwell <ncardwell@google.com>
+Date: Sat, 8 Dec 2012 19:43:22 +0000
+Subject: inet_diag: validate byte code to prevent oops in inet_diag_bc_run()
+
+
+From: Neal Cardwell <ncardwell@google.com>
+
+[ Upstream commit 405c005949e47b6e91359159c24753519ded0c67 ]
+
+Add logic to validate INET_DIAG_BC_S_COND and INET_DIAG_BC_D_COND
+operations.
+
+Previously we did not validate the inet_diag_hostcond, address family,
+address length, and prefix length. So a malicious user could make the
+kernel read beyond the end of the bytecode array by claiming to have a
+whole inet_diag_hostcond when the bytecode was not long enough to
+contain a whole inet_diag_hostcond of the given address family. Or
+they could make the kernel read up to about 27 bytes beyond the end of
+a connection address by passing a prefix length that exceeded the
+length of addresses of the given family.
+
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/inet_diag.c |   48 +++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 45 insertions(+), 3 deletions(-)
+
+--- a/net/ipv4/inet_diag.c
++++ b/net/ipv4/inet_diag.c
+@@ -504,6 +504,44 @@ static int valid_cc(const void *bc, int
+       return 0;
+ }
++/* Validate an inet_diag_hostcond. */
++static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
++                         int *min_len)
++{
++      int addr_len;
++      struct inet_diag_hostcond *cond;
++
++      /* Check hostcond space. */
++      *min_len += sizeof(struct inet_diag_hostcond);
++      if (len < *min_len)
++              return false;
++      cond = (struct inet_diag_hostcond *)(op + 1);
++
++      /* Check address family and address length. */
++      switch (cond->family) {
++      case AF_UNSPEC:
++              addr_len = 0;
++              break;
++      case AF_INET:
++              addr_len = sizeof(struct in_addr);
++              break;
++      case AF_INET6:
++              addr_len = sizeof(struct in6_addr);
++              break;
++      default:
++              return false;
++      }
++      *min_len += addr_len;
++      if (len < *min_len)
++              return false;
++
++      /* Check prefix length (in bits) vs address length (in bytes). */
++      if (cond->prefix_len > 8 * addr_len)
++              return false;
++
++      return true;
++}
++
+ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
+ {
+       const void *bc = bytecode;
+@@ -511,18 +549,22 @@ static int inet_diag_bc_audit(const void
+       while (len > 0) {
+               const struct inet_diag_bc_op *op = bc;
++              int min_len = sizeof(struct inet_diag_bc_op);
+ //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
+               switch (op->code) {
+-              case INET_DIAG_BC_AUTO:
+               case INET_DIAG_BC_S_COND:
+               case INET_DIAG_BC_D_COND:
++                      if (!valid_hostcond(bc, len, &min_len))
++                              return -EINVAL;
++                      /* fall through */
++              case INET_DIAG_BC_AUTO:
+               case INET_DIAG_BC_S_GE:
+               case INET_DIAG_BC_S_LE:
+               case INET_DIAG_BC_D_GE:
+               case INET_DIAG_BC_D_LE:
+               case INET_DIAG_BC_JMP:
+-                      if (op->no < 4 || op->no > len + 4 || op->no & 3)
++                      if (op->no < min_len || op->no > len + 4 || op->no & 3)
+                               return -EINVAL;
+                       if (op->no < len &&
+                           !valid_cc(bytecode, bytecode_len, len - op->no))
+@@ -533,7 +575,7 @@ static int inet_diag_bc_audit(const void
+               default:
+                       return -EINVAL;
+               }
+-              if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
++              if (op->yes < min_len || op->yes > len + 4 || op->yes & 3)
+                       return -EINVAL;
+               bc  += op->yes;
+               len -= op->yes;
diff --git a/queue-3.4/inet_diag-validate-port-comparison-byte-code-to-prevent-unsafe-reads.patch b/queue-3.4/inet_diag-validate-port-comparison-byte-code-to-prevent-unsafe-reads.patch
new file mode 100644 (file)
index 0000000..a7dccd4
--- /dev/null
@@ -0,0 +1,86 @@
+From 62a341ad68bffed2aee85512b1c2b84c812e4868 Mon Sep 17 00:00:00 2001
+From: Neal Cardwell <ncardwell@google.com>
+Date: Sun, 9 Dec 2012 11:09:54 +0000
+Subject: inet_diag: validate port comparison byte code to prevent unsafe reads
+
+
+From: Neal Cardwell <ncardwell@google.com>
+
+[ Upstream commit 5e1f54201cb481f40a04bc47e1bc8c093a189e23 ]
+
+Add logic to verify that a port comparison byte code operation
+actually has the second inet_diag_bc_op from which we read the port
+for such operations.
+
+Previously the code blindly referenced op[1] without first checking
+whether a second inet_diag_bc_op struct could fit there. So a
+malicious user could make the kernel read 4 bytes beyond the end of
+the bytecode array by claiming to have a whole port comparison byte
+code (2 inet_diag_bc_op structs) when in fact the bytecode was not
+long enough to hold both.
+
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/inet_diag.c |   31 ++++++++++++++++++++++++-------
+ 1 file changed, 24 insertions(+), 7 deletions(-)
+
+--- a/net/ipv4/inet_diag.c
++++ b/net/ipv4/inet_diag.c
+@@ -548,6 +548,17 @@ static bool valid_hostcond(const struct
+       return true;
+ }
++/* Validate a port comparison operator. */
++static inline bool valid_port_comparison(const struct inet_diag_bc_op *op,
++                                       int len, int *min_len)
++{
++      /* Port comparisons put the port in a follow-on inet_diag_bc_op. */
++      *min_len += sizeof(struct inet_diag_bc_op);
++      if (len < *min_len)
++              return false;
++      return true;
++}
++
+ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
+ {
+       const void *bc = bytecode;
+@@ -563,24 +574,30 @@ static int inet_diag_bc_audit(const void
+               case INET_DIAG_BC_D_COND:
+                       if (!valid_hostcond(bc, len, &min_len))
+                               return -EINVAL;
+-                      /* fall through */
+-              case INET_DIAG_BC_AUTO:
++                      break;
+               case INET_DIAG_BC_S_GE:
+               case INET_DIAG_BC_S_LE:
+               case INET_DIAG_BC_D_GE:
+               case INET_DIAG_BC_D_LE:
+-              case INET_DIAG_BC_JMP:
+-                      if (op->no < min_len || op->no > len + 4 || op->no & 3)
+-                              return -EINVAL;
+-                      if (op->no < len &&
+-                          !valid_cc(bytecode, bytecode_len, len - op->no))
++                      if (!valid_port_comparison(bc, len, &min_len))
+                               return -EINVAL;
+                       break;
++              case INET_DIAG_BC_AUTO:
++              case INET_DIAG_BC_JMP:
+               case INET_DIAG_BC_NOP:
+                       break;
+               default:
+                       return -EINVAL;
+               }
++
++              if (op->code != INET_DIAG_BC_NOP) {
++                      if (op->no < min_len || op->no > len + 4 || op->no & 3)
++                              return -EINVAL;
++                      if (op->no < len &&
++                          !valid_cc(bytecode, bytecode_len, len - op->no))
++                              return -EINVAL;
++              }
++
+               if (op->yes < min_len || op->yes > len + 4 || op->yes & 3)
+                       return -EINVAL;
+               bc  += op->yes;
diff --git a/queue-3.4/ipv4-ip_check_defrag-must-not-modify-skb-before-unsharing.patch b/queue-3.4/ipv4-ip_check_defrag-must-not-modify-skb-before-unsharing.patch
new file mode 100644 (file)
index 0000000..239e580
--- /dev/null
@@ -0,0 +1,68 @@
+From 62c30ed6c731bf4a9961856dffee55b2c8f89119 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Sun, 9 Dec 2012 23:41:06 +0000
+Subject: ipv4: ip_check_defrag must not modify skb before unsharing
+
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 1bf3751ec90cc3174e01f0d701e8449ce163d113 ]
+
+ip_check_defrag() might be called from af_packet within the
+RX path where shared SKBs are used, so it must not modify
+the input SKB before it has unshared it for defragmentation.
+Use skb_copy_bits() to get the IP header and only pull in
+everything later.
+
+The same is true for the other caller in macvlan as it is
+called from dev->rx_handler which can also get a shared SKB.
+
+Reported-by: Eric Leblond <eric@regit.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_fragment.c |   19 +++++++++----------
+ 1 file changed, 9 insertions(+), 10 deletions(-)
+
+--- a/net/ipv4/ip_fragment.c
++++ b/net/ipv4/ip_fragment.c
+@@ -685,28 +685,27 @@ EXPORT_SYMBOL(ip_defrag);
+ struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
+ {
+-      const struct iphdr *iph;
++      struct iphdr iph;
+       u32 len;
+       if (skb->protocol != htons(ETH_P_IP))
+               return skb;
+-      if (!pskb_may_pull(skb, sizeof(struct iphdr)))
++      if (!skb_copy_bits(skb, 0, &iph, sizeof(iph)))
+               return skb;
+-      iph = ip_hdr(skb);
+-      if (iph->ihl < 5 || iph->version != 4)
++      if (iph.ihl < 5 || iph.version != 4)
+               return skb;
+-      if (!pskb_may_pull(skb, iph->ihl*4))
+-              return skb;
+-      iph = ip_hdr(skb);
+-      len = ntohs(iph->tot_len);
+-      if (skb->len < len || len < (iph->ihl * 4))
++
++      len = ntohs(iph.tot_len);
++      if (skb->len < len || len < (iph.ihl * 4))
+               return skb;
+-      if (ip_is_fragment(ip_hdr(skb))) {
++      if (ip_is_fragment(&iph)) {
+               skb = skb_share_check(skb, GFP_ATOMIC);
+               if (skb) {
++                      if (!pskb_may_pull(skb, iph.ihl*4))
++                              return skb;
+                       if (pskb_trim_rcsum(skb, len))
+                               return skb;
+                       memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
diff --git a/queue-3.4/irda-sir_dev-fix-copy-paste-typo.patch b/queue-3.4/irda-sir_dev-fix-copy-paste-typo.patch
new file mode 100644 (file)
index 0000000..4ed0f0d
--- /dev/null
@@ -0,0 +1,28 @@
+From 682049691034d38f8eecb15740d7bc2dd3028297 Mon Sep 17 00:00:00 2001
+From: Alexander Shiyan <shc_work@mail.ru>
+Date: Tue, 20 Nov 2012 09:59:11 +0000
+Subject: irda: sir_dev: Fix copy/paste typo
+
+
+From: Alexander Shiyan <shc_work@mail.ru>
+
+[ Upstream commit 2355a62bcbdcc4b567425bab036bfab6ade87eed ]
+
+Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/irda/sir_dev.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/irda/sir_dev.c
++++ b/drivers/net/irda/sir_dev.c
+@@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct wor
+                       break;
+               case SIRDEV_STATE_DONGLE_SPEED:
+-                      if (dev->dongle_drv->reset) {
++                      if (dev->dongle_drv->set_speed) {
+                               ret = dev->dongle_drv->set_speed(dev, fsm->param);
+                               if (ret < 0) {
+                                       fsm->result = ret;
diff --git a/queue-3.4/ne2000-add-the-right-platform-device.patch b/queue-3.4/ne2000-add-the-right-platform-device.patch
new file mode 100644 (file)
index 0000000..103d8c2
--- /dev/null
@@ -0,0 +1,30 @@
+From 436fa5c524b6f0b1a307f5e09a34c520f17b6da8 Mon Sep 17 00:00:00 2001
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 20 Nov 2012 06:31:57 +0000
+Subject: ne2000: add the right platform device
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+[ Upstream commit da9da01d9199b5bb15289d0859053c9aa3a34ac0 ]
+
+Without this udev doesn't have a way to key the ne device to the platform
+device.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/8390/ne.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/8390/ne.c
++++ b/drivers/net/ethernet/8390/ne.c
+@@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct pl
+               dev->irq = irq[this_dev];
+               dev->mem_end = bad[this_dev];
+       }
++      SET_NETDEV_DEV(dev, &pdev->dev);
+       err = do_ne_probe(dev);
+       if (err) {
+               free_netdev(dev);
diff --git a/queue-3.4/sctp-fix-enomem-result-with-invalid-user-space-pointer-in-sendto-syscall.patch b/queue-3.4/sctp-fix-enomem-result-with-invalid-user-space-pointer-in-sendto-syscall.patch
new file mode 100644 (file)
index 0000000..18838a0
--- /dev/null
@@ -0,0 +1,117 @@
+From 29e5342659bef7411affb2876a322da74e0ac1b8 Mon Sep 17 00:00:00 2001
+From: Tommi Rantala <tt.rantala@gmail.com>
+Date: Thu, 22 Nov 2012 03:23:16 +0000
+Subject: sctp: fix -ENOMEM result with invalid user space pointer in sendto() syscall
+
+
+From: Tommi Rantala <tt.rantala@gmail.com>
+
+[ Upstream commit 6e51fe7572590d8d86e93b547fab6693d305fd0d ]
+
+Consider the following program, that sets the second argument to the
+sendto() syscall incorrectly:
+
+ #include <string.h>
+ #include <arpa/inet.h>
+ #include <sys/socket.h>
+
+ int main(void)
+ {
+         int fd;
+         struct sockaddr_in sa;
+
+         fd = socket(AF_INET, SOCK_STREAM, 132 /*IPPROTO_SCTP*/);
+         if (fd < 0)
+                 return 1;
+
+         memset(&sa, 0, sizeof(sa));
+         sa.sin_family = AF_INET;
+         sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+         sa.sin_port = htons(11111);
+
+         sendto(fd, NULL, 1, 0, (struct sockaddr *)&sa, sizeof(sa));
+
+         return 0;
+ }
+
+We get -ENOMEM:
+
+ $ strace -e sendto ./demo
+ sendto(3, NULL, 1, 0, {sa_family=AF_INET, sin_port=htons(11111), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ENOMEM (Cannot allocate memory)
+
+Propagate the error code from sctp_user_addto_chunk(), so that we will
+tell user space what actually went wrong:
+
+ $ strace -e sendto ./demo
+ sendto(3, NULL, 1, 0, {sa_family=AF_INET, sin_port=htons(11111), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EFAULT (Bad address)
+
+Noticed while running Trinity (the syscall fuzzer).
+
+Signed-off-by: Tommi Rantala <tt.rantala@gmail.com>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/chunk.c  |   13 +++++++++----
+ net/sctp/socket.c |    4 ++--
+ 2 files changed, 11 insertions(+), 6 deletions(-)
+
+--- a/net/sctp/chunk.c
++++ b/net/sctp/chunk.c
+@@ -183,7 +183,7 @@ struct sctp_datamsg *sctp_datamsg_from_u
+       msg = sctp_datamsg_new(GFP_KERNEL);
+       if (!msg)
+-              return NULL;
++              return ERR_PTR(-ENOMEM);
+       /* Note: Calculate this outside of the loop, so that all fragments
+        * have the same expiration.
+@@ -280,8 +280,11 @@ struct sctp_datamsg *sctp_datamsg_from_u
+               chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
+-              if (!chunk)
++              if (!chunk) {
++                      err = -ENOMEM;
+                       goto errout;
++              }
++
+               err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
+               if (err < 0)
+                       goto errout_chunk_free;
+@@ -315,8 +318,10 @@ struct sctp_datamsg *sctp_datamsg_from_u
+               chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
+-              if (!chunk)
++              if (!chunk) {
++                      err = -ENOMEM;
+                       goto errout;
++              }
+               err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
+@@ -342,7 +347,7 @@ errout:
+               sctp_chunk_free(chunk);
+       }
+       sctp_datamsg_put(msg);
+-      return NULL;
++      return ERR_PTR(err);
+ }
+ /* Check whether this message has expired. */
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -1908,8 +1908,8 @@ SCTP_STATIC int sctp_sendmsg(struct kioc
+       /* Break the message into multiple chunks of maximum size. */
+       datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
+-      if (!datamsg) {
+-              err = -ENOMEM;
++      if (IS_ERR(datamsg)) {
++              err = PTR_ERR(datamsg);
+               goto out_free;
+       }
diff --git a/queue-3.4/sctp-fix-memory-leak-in-sctp_datamsg_from_user-when-copy-from-user-space-fails.patch b/queue-3.4/sctp-fix-memory-leak-in-sctp_datamsg_from_user-when-copy-from-user-space-fails.patch
new file mode 100644 (file)
index 0000000..2aa3d18
--- /dev/null
@@ -0,0 +1,77 @@
+From 41d64473d689949d1d11779d816d4cefb38e47b3 Mon Sep 17 00:00:00 2001
+From: Tommi Rantala <tt.rantala@gmail.com>
+Date: Tue, 27 Nov 2012 04:01:46 +0000
+Subject: sctp: fix memory leak in sctp_datamsg_from_user() when copy from user space fails
+
+
+From: Tommi Rantala <tt.rantala@gmail.com>
+
+[ Upstream commit be364c8c0f17a3dd42707b5a090b318028538eb9 ]
+
+Trinity (the syscall fuzzer) discovered a memory leak in SCTP,
+reproducible e.g. with the sendto() syscall by passing invalid
+user space pointer in the second argument:
+
+ #include <string.h>
+ #include <arpa/inet.h>
+ #include <sys/socket.h>
+
+ int main(void)
+ {
+         int fd;
+         struct sockaddr_in sa;
+
+         fd = socket(AF_INET, SOCK_STREAM, 132 /*IPPROTO_SCTP*/);
+         if (fd < 0)
+                 return 1;
+
+         memset(&sa, 0, sizeof(sa));
+         sa.sin_family = AF_INET;
+         sa.sin_addr.s_addr = inet_addr("127.0.0.1");
+         sa.sin_port = htons(11111);
+
+         sendto(fd, NULL, 1, 0, (struct sockaddr *)&sa, sizeof(sa));
+
+         return 0;
+ }
+
+As far as I can tell, the leak has been around since ~2003.
+
+Signed-off-by: Tommi Rantala <tt.rantala@gmail.com>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/chunk.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/net/sctp/chunk.c
++++ b/net/sctp/chunk.c
+@@ -284,7 +284,7 @@ struct sctp_datamsg *sctp_datamsg_from_u
+                       goto errout;
+               err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
+               if (err < 0)
+-                      goto errout;
++                      goto errout_chunk_free;
+               offset += len;
+@@ -324,7 +324,7 @@ struct sctp_datamsg *sctp_datamsg_from_u
+               __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
+                          - (__u8 *)chunk->skb->data);
+               if (err < 0)
+-                      goto errout;
++                      goto errout_chunk_free;
+               sctp_datamsg_assign(msg, chunk);
+               list_add_tail(&chunk->frag_list, &msg->chunks);
+@@ -332,6 +332,9 @@ struct sctp_datamsg *sctp_datamsg_from_u
+       return msg;
++errout_chunk_free:
++      sctp_chunk_free(chunk);
++
+ errout:
+       list_for_each_safe(pos, temp, &msg->chunks) {
+               list_del_init(pos);
diff --git a/queue-3.4/series b/queue-3.4/series
new file mode 100644 (file)
index 0000000..dd10f94
--- /dev/null
@@ -0,0 +1,12 @@
+bonding-bonding-driver-does-not-consider-the-gso_max_size-gso_max_segs-setting-of-slave-devices.patch
+bonding-fix-race-condition-in-bonding_store_slaves_active.patch
+sctp-fix-memory-leak-in-sctp_datamsg_from_user-when-copy-from-user-space-fails.patch
+sctp-fix-enomem-result-with-invalid-user-space-pointer-in-sendto-syscall.patch
+ne2000-add-the-right-platform-device.patch
+irda-sir_dev-fix-copy-paste-typo.patch
+ipv4-ip_check_defrag-must-not-modify-skb-before-unsharing.patch
+usb-ipheth-add-iphone-5-support.patch
+inet_diag-fix-oops-for-ipv4-af_inet6-tcp-syn-recv-state.patch
+inet_diag-validate-byte-code-to-prevent-oops-in-inet_diag_bc_run.patch
+inet_diag-avoid-unsafe-and-nonsensical-prefix-matches-in-inet_diag_bc_run.patch
+inet_diag-validate-port-comparison-byte-code-to-prevent-unsafe-reads.patch
diff --git a/queue-3.4/usb-ipheth-add-iphone-5-support.patch b/queue-3.4/usb-ipheth-add-iphone-5-support.patch
new file mode 100644 (file)
index 0000000..5fbf42f
--- /dev/null
@@ -0,0 +1,44 @@
+From 00b664505146724adce37e5e1317a070e5b22480 Mon Sep 17 00:00:00 2001
+From: Jay Purohit <jspurohit@velocitylimitless.com>
+Date: Sun, 14 Oct 2012 07:07:21 +0000
+Subject: usb/ipheth: Add iPhone 5 support
+
+
+From: Jay Purohit <jspurohit@velocitylimitless.com>
+
+[ Upstream commit af1b85e49089f945deb46258b0fc4bc9910afb22 ]
+
+I noticed that the iPhone ethernet driver did not support
+iPhone 5. I quickly added support to it in my kernel, here's
+a patch.
+
+Signed-off-by: Jay Purohit <jspurohit@velocitylimitless.com>
+Acked-by: Valdis Kletnieks <valdis.kletnieks@vt.edu>
+Signed-off-by: Jan Ceuleers <jan.ceuleers@computer.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/ipheth.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/net/usb/ipheth.c
++++ b/drivers/net/usb/ipheth.c
+@@ -62,6 +62,7 @@
+ #define USB_PRODUCT_IPAD 0x129a
+ #define USB_PRODUCT_IPHONE_4_VZW 0x129c
+ #define USB_PRODUCT_IPHONE_4S 0x12a0
++#define USB_PRODUCT_IPHONE_5  0x12a8
+ #define IPHETH_USBINTF_CLASS    255
+ #define IPHETH_USBINTF_SUBCLASS 253
+@@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table
+               USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
++      { USB_DEVICE_AND_INTERFACE_INFO(
++              USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5,
++              IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
++              IPHETH_USBINTF_PROTO) },
+       { }
+ };
+ MODULE_DEVICE_TABLE(usb, ipheth_table);