From da31c01420c7a1751f99bea856313601f121f78a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Dec 2012 13:00:47 -0800 Subject: [PATCH] 3.4-stable patches 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 --- ...so_max_segs-setting-of-slave-devices.patch | 48 +++++++ ...ition-in-bonding_store_slaves_active.patch | 44 +++++++ ...l-prefix-matches-in-inet_diag_bc_run.patch | 81 ++++++++++++ ...for-ipv4-af_inet6-tcp-syn-recv-state.patch | 113 +++++++++++++++++ ...-to-prevent-oops-in-inet_diag_bc_run.patch | 110 ++++++++++++++++ ...on-byte-code-to-prevent-unsafe-reads.patch | 86 +++++++++++++ ...must-not-modify-skb-before-unsharing.patch | 68 ++++++++++ .../irda-sir_dev-fix-copy-paste-typo.patch | 28 +++++ ...ne2000-add-the-right-platform-device.patch | 30 +++++ ...user-space-pointer-in-sendto-syscall.patch | 117 ++++++++++++++++++ ...user-when-copy-from-user-space-fails.patch | 77 ++++++++++++ queue-3.4/series | 12 ++ .../usb-ipheth-add-iphone-5-support.patch | 44 +++++++ 13 files changed, 858 insertions(+) create mode 100644 queue-3.4/bonding-bonding-driver-does-not-consider-the-gso_max_size-gso_max_segs-setting-of-slave-devices.patch create mode 100644 queue-3.4/bonding-fix-race-condition-in-bonding_store_slaves_active.patch create mode 100644 queue-3.4/inet_diag-avoid-unsafe-and-nonsensical-prefix-matches-in-inet_diag_bc_run.patch create mode 100644 queue-3.4/inet_diag-fix-oops-for-ipv4-af_inet6-tcp-syn-recv-state.patch create mode 100644 queue-3.4/inet_diag-validate-byte-code-to-prevent-oops-in-inet_diag_bc_run.patch create mode 100644 queue-3.4/inet_diag-validate-port-comparison-byte-code-to-prevent-unsafe-reads.patch create mode 100644 queue-3.4/ipv4-ip_check_defrag-must-not-modify-skb-before-unsharing.patch create mode 100644 queue-3.4/irda-sir_dev-fix-copy-paste-typo.patch create mode 100644 queue-3.4/ne2000-add-the-right-platform-device.patch create mode 100644 queue-3.4/sctp-fix-enomem-result-with-invalid-user-space-pointer-in-sendto-syscall.patch create mode 100644 queue-3.4/sctp-fix-memory-leak-in-sctp_datamsg_from_user-when-copy-from-user-space-fails.patch create mode 100644 queue-3.4/series create mode 100644 queue-3.4/usb-ipheth-add-iphone-5-support.patch 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 index 00000000000..e7d3dde86d5 --- /dev/null +++ b/queue-3.4/bonding-bonding-driver-does-not-consider-the-gso_max_size-gso_max_segs-setting-of-slave-devices.patch @@ -0,0 +1,48 @@ +From b680f523aeb9d6f79355e15b531b1af09570dee4 Mon Sep 17 00:00:00 2001 +From: Sarveshwar Bandi +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 + +[ 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 +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..fa7fe246dde --- /dev/null +++ b/queue-3.4/bonding-fix-race-condition-in-bonding_store_slaves_active.patch @@ -0,0 +1,44 @@ +From b9be04947edf4c74a81ae9040e33a624d66620d3 Mon Sep 17 00:00:00 2001 +From: "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" + +[ 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 +Signed-off-by: Jay Vosburgh +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4c6d213f8e3 --- /dev/null +++ b/queue-3.4/inet_diag-avoid-unsafe-and-nonsensical-prefix-matches-in-inet_diag_bc_run.patch @@ -0,0 +1,81 @@ +From a81faa0202b4a6bd474f64aecc83d52506690981 Mon Sep 17 00:00:00 2001 +From: Neal Cardwell +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 + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..7824345f631 --- /dev/null +++ b/queue-3.4/inet_diag-fix-oops-for-ipv4-af_inet6-tcp-syn-recv-state.patch @@ -0,0 +1,113 @@ +From 860f3ff2f6cb1f393c6dbae13bf7f333f4854156 Mon Sep 17 00:00:00 2001 +From: Neal Cardwell +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 + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..d0a40c40773 --- /dev/null +++ b/queue-3.4/inet_diag-validate-byte-code-to-prevent-oops-in-inet_diag_bc_run.patch @@ -0,0 +1,110 @@ +From b834907c7c553dc02358417a535b8b486f481bd6 Mon Sep 17 00:00:00 2001 +From: Neal Cardwell +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 + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a7dccd498e4 --- /dev/null +++ b/queue-3.4/inet_diag-validate-port-comparison-byte-code-to-prevent-unsafe-reads.patch @@ -0,0 +1,86 @@ +From 62a341ad68bffed2aee85512b1c2b84c812e4868 Mon Sep 17 00:00:00 2001 +From: Neal Cardwell +Date: Sun, 9 Dec 2012 11:09:54 +0000 +Subject: inet_diag: validate port comparison byte code to prevent unsafe reads + + +From: Neal Cardwell + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..239e5803de8 --- /dev/null +++ b/queue-3.4/ipv4-ip_check_defrag-must-not-modify-skb-before-unsharing.patch @@ -0,0 +1,68 @@ +From 62c30ed6c731bf4a9961856dffee55b2c8f89119 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Sun, 9 Dec 2012 23:41:06 +0000 +Subject: ipv4: ip_check_defrag must not modify skb before unsharing + + +From: Johannes Berg + +[ 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 +Cc: stable@vger.kernel.org +Signed-off-by: Johannes Berg +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..4ed0f0d2fe4 --- /dev/null +++ b/queue-3.4/irda-sir_dev-fix-copy-paste-typo.patch @@ -0,0 +1,28 @@ +From 682049691034d38f8eecb15740d7bc2dd3028297 Mon Sep 17 00:00:00 2001 +From: Alexander Shiyan +Date: Tue, 20 Nov 2012 09:59:11 +0000 +Subject: irda: sir_dev: Fix copy/paste typo + + +From: Alexander Shiyan + +[ Upstream commit 2355a62bcbdcc4b567425bab036bfab6ade87eed ] + +Signed-off-by: Alexander Shiyan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..103d8c2926e --- /dev/null +++ b/queue-3.4/ne2000-add-the-right-platform-device.patch @@ -0,0 +1,30 @@ +From 436fa5c524b6f0b1a307f5e09a34c520f17b6da8 Mon Sep 17 00:00:00 2001 +From: Alan Cox +Date: Tue, 20 Nov 2012 06:31:57 +0000 +Subject: ne2000: add the right platform device + + +From: Alan Cox + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..18838a08380 --- /dev/null +++ b/queue-3.4/sctp-fix-enomem-result-with-invalid-user-space-pointer-in-sendto-syscall.patch @@ -0,0 +1,117 @@ +From 29e5342659bef7411affb2876a322da74e0ac1b8 Mon Sep 17 00:00:00 2001 +From: Tommi Rantala +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 + +[ Upstream commit 6e51fe7572590d8d86e93b547fab6693d305fd0d ] + +Consider the following program, that sets the second argument to the +sendto() syscall incorrectly: + + #include + #include + #include + + 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 +Acked-by: Vlad Yasevich +Acked-by: Neil Horman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..2aa3d18ee38 --- /dev/null +++ b/queue-3.4/sctp-fix-memory-leak-in-sctp_datamsg_from_user-when-copy-from-user-space-fails.patch @@ -0,0 +1,77 @@ +From 41d64473d689949d1d11779d816d4cefb38e47b3 Mon Sep 17 00:00:00 2001 +From: Tommi Rantala +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 + +[ 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 + #include + #include + + 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 +Acked-by: Vlad Yasevich +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..dd10f946f25 --- /dev/null +++ b/queue-3.4/series @@ -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 index 00000000000..5fbf42fed7b --- /dev/null +++ b/queue-3.4/usb-ipheth-add-iphone-5-support.patch @@ -0,0 +1,44 @@ +From 00b664505146724adce37e5e1317a070e5b22480 Mon Sep 17 00:00:00 2001 +From: Jay Purohit +Date: Sun, 14 Oct 2012 07:07:21 +0000 +Subject: usb/ipheth: Add iPhone 5 support + + +From: Jay Purohit + +[ 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 +Acked-by: Valdis Kletnieks +Signed-off-by: Jan Ceuleers +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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); -- 2.47.3