diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-07-24 07:37:42 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-07-24 07:40:28 +0000 |
commit | 2090f6be2eb8aa04ae81c1bf456f4dc3709ac886 (patch) | |
tree | a7c177a47ea3791b1a4ddd70cf0207c95c874c3e | |
parent | 2f83f79dde103d04db044584d80034181020f6ea (diff) | |
download | aports-2090f6be2eb8aa04ae81c1bf456f4dc3709ac886.tar.bz2 aports-2090f6be2eb8aa04ae81c1bf456f4dc3709ac886.tar.xz |
main/linux-grsec: various security fixes (CVE-2013-4125, CVE-2013-4127)
-rw-r--r-- | main/linux-grsec/APKBUILD | 10 | ||||
-rw-r--r-- | main/linux-grsec/grsecurity-2.9.1-3.9.11-unofficial-1.patch (renamed from main/linux-grsec/grsecurity-2.9.1-3.9.11-unofficial-0.patch) | 398 |
2 files changed, 389 insertions, 19 deletions
diff --git a/main/linux-grsec/APKBUILD b/main/linux-grsec/APKBUILD index 3bf39595bf..df98cbc9dd 100644 --- a/main/linux-grsec/APKBUILD +++ b/main/linux-grsec/APKBUILD @@ -7,7 +7,7 @@ case $pkgver in *.*.*) _kernver=${pkgver%.*};; *.*) _kernver=${pkgver};; esac -pkgrel=0 +pkgrel=1 pkgdesc="Linux kernel with grsecurity" url=http://grsecurity.net depends="mkinitfs linux-firmware" @@ -17,7 +17,7 @@ _config=${config:-kernelconfig.${CARCH}} install= source="http://ftp.kernel.org/pub/linux/kernel/v3.x/linux-$_kernver.tar.xz http://ftp.kernel.org/pub/linux/kernel/v3.x/patch-$pkgver.xz - grsecurity-2.9.1-3.9.11-unofficial-0.patch + grsecurity-2.9.1-3.9.11-unofficial-1.patch 0001-net-inform-NETDEV_CHANGE-callbacks-which-flags-were-.patch 0002-arp-flush-arp-cache-on-IFF_NOARP-change.patch @@ -150,7 +150,7 @@ dev() { md5sums="4348c9b6b2eb3144d601e87c19d5d909 linux-3.9.tar.xz 552146435b7ecc414bf8e3cd8bb6ac4a patch-3.9.11.xz -6d3715f39d6c9e418550443ddf472ec8 grsecurity-2.9.1-3.9.11-unofficial-0.patch +0888981bb55e0d27b6ed39edcc7ee45a grsecurity-2.9.1-3.9.11-unofficial-1.patch a16f11b12381efb3bec79b9bfb329836 0001-net-inform-NETDEV_CHANGE-callbacks-which-flags-were-.patch 656ae7b10dd2f18dbfa1011041d08d60 0002-arp-flush-arp-cache-on-IFF_NOARP-change.patch aa454ffb96428586447775c21449e284 0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch @@ -161,7 +161,7 @@ d89089b3c7eb94dd9f65cf8a357fc36d kernelconfig.x86 eb147f09fef5996a488c247790205cd6 kernelconfig.x86_64" sha256sums="60bc3e64ee5dc778de2cd7cd7640abf518a4c9d4f31b8ed624e16fad53f54541 linux-3.9.tar.xz 29be11d16ef152ae1858d567cbf45f0da0193adf364826f5e3fa8b2fcd839682 patch-3.9.11.xz -09787452cd5f7b0bfcef6c27f4f64c3a8c1f46fad69a6c9604883a4f4d2924df grsecurity-2.9.1-3.9.11-unofficial-0.patch +fa2223e87b38e225568a36ee2eb00976f74bc109e2ccc21c93abed676f58e3ad grsecurity-2.9.1-3.9.11-unofficial-1.patch 6af3757ac36a6cd3cda7b0a71b08143726383b19261294a569ad7f4042c72df3 0001-net-inform-NETDEV_CHANGE-callbacks-which-flags-were-.patch dc8e82108615657f1fb9d641efd42255a5761c06edde1b00a41ae0d314d548f0 0002-arp-flush-arp-cache-on-IFF_NOARP-change.patch 0985caa0f3ee8ed0959aeaa4214f5f8057ae8e61d50dcae39194912d31e14892 0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch @@ -172,7 +172,7 @@ de3c17420664ae4e52826c6e602aade0deeae94f72253f85b3e48771491ed5d6 kernelconfig.x e1cce320f207cc2ba72b9d154c7060c8cbed52c664319dfd21f24e8956d0bf3e kernelconfig.x86_64" sha512sums="77fa521f42380409f8ab400c26f7b00e225cb075ef40834bb263325cfdcc3e65aef8511ec2fc2b50bbf4f50e226fb5ab07d7a479aaf09162adbbf318325d0790 linux-3.9.tar.xz c3a0be102d816ae06d7dfdd2738915fc2114cb9bb488b03b34e4f52f2367dcba4d8cb8ba203687bf694c2dcad36d70bb9d3121ac739a28e2c7fb2c44f08a9c71 patch-3.9.11.xz -a6a4b7fc2b5a532845dc31f7ba539b4f9b643750a4e96870e3fc4ac516953d456e28246c0964493ba5ddd41f5e65f2ca99b9e71d2a3d94dba2385be5a9dcceac grsecurity-2.9.1-3.9.11-unofficial-0.patch +59e34764fca125d097d1826042dce0e6fb0bf53eb97935b591e57674fb755491d78b1180a6db6253a869ffe56f7ceddf2e80f24812319e2b2f623d3e100aaa00 grsecurity-2.9.1-3.9.11-unofficial-1.patch 81e78593288e8b0fd2c03ea9fc1450323887707f087e911f172450a122bc9b591ee83394836789730d951aeec13d0b75a64e1c05f04364abf8f80d883ddc4a02 0001-net-inform-NETDEV_CHANGE-callbacks-which-flags-were-.patch 51ecb15b669f6a82940a13a38939116e003bf5dfd24496771c8279e907b72adcc63d607f0340a2940d757e12ddadb7d45c7af78ae311d284935a6296dbcac00c 0002-arp-flush-arp-cache-on-IFF_NOARP-change.patch 57d0a8bd35d19cf657ded58efe24517d2252aec6984040713ba173a34edb5887ececaa2985076bc6a149eaa57639fd98a042c1c2d226ed4ad8dd5ed0e230717e 0003-ipv4-properly-refresh-rtable-entries-on-pmtu-redirec.patch diff --git a/main/linux-grsec/grsecurity-2.9.1-3.9.11-unofficial-0.patch b/main/linux-grsec/grsecurity-2.9.1-3.9.11-unofficial-1.patch index 2aebee9454..932805c959 100644 --- a/main/linux-grsec/grsecurity-2.9.1-3.9.11-unofficial-0.patch +++ b/main/linux-grsec/grsecurity-2.9.1-3.9.11-unofficial-1.patch @@ -39865,6 +39865,42 @@ index aee7671..3ca2651 100644 /* multicast configuration controlling object */ bnx2x_init_mcast_obj(bp, &bp->mcast_obj, bp->fp->cl_id, bp->fp->cid, +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +index edfa67a..d6c52ae 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +@@ -960,6 +960,9 @@ static int bnx2x_set_dump(struct net_device *dev, struct ethtool_dump *val) + struct bnx2x *bp = netdev_priv(dev); + + /* Use the ethtool_dump "flag" field as the dump preset index */ ++ if (val->flag < 1 || val->flag > DUMP_MAX_PRESETS) ++ return -EINVAL; ++ + bp->dump_preset_idx = val->flag; + return 0; + } +@@ -986,8 +989,6 @@ static int bnx2x_get_dump_data(struct net_device *dev, + struct bnx2x *bp = netdev_priv(dev); + struct dump_header dump_hdr = {0}; + +- memset(p, 0, dump->len); +- + /* Disable parity attentions as long as following dump may + * cause false alarms by reading never written registers. We + * will re-enable parity attentions right after the dump. +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +index c50696b..cf96f52 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +@@ -11394,6 +11394,8 @@ static int bnx2x_init_bp(struct bnx2x *bp) + bp->min_msix_vec_cnt = 2; + BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt); + ++ bp->dump_preset_idx = 1; ++ + return rc; + } + diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 7306416..5fb7fb5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -39929,6 +39965,20 @@ index 6e8bc9d..94d957d 100644 break; default: return -EINVAL; +diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +index 2b5e621..32187b8 100644 +--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c ++++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +@@ -3036,7 +3036,9 @@ static void t3_io_resume(struct pci_dev *pdev) + CH_ALERT(adapter, "adapter recovering, PEX ERR 0x%x\n", + t3_read_reg(adapter, A_PCIE_PEX_ERR)); + ++ rtnl_lock(); + t3_resume_ports(adapter); ++ rtnl_unlock(); + } + + static const struct pci_error_handlers t3_err_handler = { diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.h b/drivers/net/ethernet/chelsio/cxgb3/l2t.h index 8cffcdf..aadf043 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/l2t.h @@ -44863,6 +44913,56 @@ index 6ef94bc..1b41265 100644 } /* +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index dfff647..3a19054 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -857,7 +857,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) + mutex_unlock(&vq->mutex); + + if (oldubufs) { +- vhost_ubuf_put_and_wait(oldubufs); ++ vhost_ubuf_put_and_wait_and_free(oldubufs); + mutex_lock(&vq->mutex); + vhost_zerocopy_signal_used(n, vq); + mutex_unlock(&vq->mutex); +@@ -875,7 +875,7 @@ err_used: + rcu_assign_pointer(vq->private_data, oldsock); + vhost_net_enable_vq(n, vq); + if (ubufs) +- vhost_ubuf_put_and_wait(ubufs); ++ vhost_ubuf_put_and_wait_and_free(ubufs); + err_ubufs: + fput(sock->file); + err_vq: +diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c +index 9759249..2e2524c 100644 +--- a/drivers/vhost/vhost.c ++++ b/drivers/vhost/vhost.c +@@ -1581,5 +1581,11 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs) + { + kref_put(&ubufs->kref, vhost_zerocopy_done_signal); + wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount)); ++} ++ ++void vhost_ubuf_put_and_wait_and_free(struct vhost_ubuf_ref *ubufs) ++{ ++ vhost_ubuf_put_and_wait(ubufs); + kfree(ubufs); + } ++ +diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h +index 17261e2..70cbe6f 100644 +--- a/drivers/vhost/vhost.h ++++ b/drivers/vhost/vhost.h +@@ -63,6 +63,7 @@ struct vhost_ubuf_ref { + struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy); + void vhost_ubuf_put(struct vhost_ubuf_ref *); + void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *); ++void vhost_ubuf_put_and_wait_and_free(struct vhost_ubuf_ref *); + + struct ubuf_info; + diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 8c55011..eed4ae1a 100644 --- a/drivers/video/aty/aty128fb.c @@ -73352,6 +73452,18 @@ index a345480..3c65cf4 100644 }; #define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0])) +diff --git a/include/net/udp.h b/include/net/udp.h +index 065f379..ad99eed 100644 +--- a/include/net/udp.h ++++ b/include/net/udp.h +@@ -181,6 +181,7 @@ extern int udp_get_port(struct sock *sk, unsigned short snum, + extern void udp_err(struct sk_buff *, u32); + extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t len); ++extern int udp_push_pending_frames(struct sock *sk); + extern void udp_flush_pending_frames(struct sock *sk); + extern int udp_rcv(struct sk_buff *skb); + extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 24c8886..e6fb816 100644 --- a/include/net/xfrm.h @@ -86463,6 +86575,48 @@ index 6cc0481..59cfb00 100644 } } EXPORT_SYMBOL(dev_load); +diff --git a/net/core/ethtool.c b/net/core/ethtool.c +index 41f4bdf..9e7c219 100644 +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -1314,10 +1314,19 @@ static int ethtool_get_dump_data(struct net_device *dev, + if (ret) + return ret; + +- len = (tmp.len > dump.len) ? dump.len : tmp.len; ++ len = min(tmp.len, dump.len); + if (!len) + return -EFAULT; + ++ /* Don't ever let the driver think there's more space available ++ * than it requested with .get_dump_flag(). ++ */ ++ dump.len = len; ++ ++ /* Always allocate enough space to hold the whole thing so that the ++ * driver does not need to check the length and bother with partial ++ * dumping. ++ */ + data = vzalloc(tmp.len); + if (!data) + return -ENOMEM; +@@ -1325,6 +1334,16 @@ static int ethtool_get_dump_data(struct net_device *dev, + if (ret) + goto out; + ++ /* There are two sane possibilities: ++ * 1. The driver's .get_dump_data() does not touch dump.len. ++ * 2. Or it may set dump.len to how much it really writes, which ++ * should be tmp.len (or len if it can do a partial dump). ++ * In any case respond to userspace with the actual length of data ++ * it's receiving. ++ */ ++ WARN_ON(dump.len != len && dump.len != tmp.len); ++ dump.len = len; ++ + if (copy_to_user(useraddr, &dump, sizeof(dump))) { + ret = -EFAULT; + goto out; diff --git a/net/core/flow.c b/net/core/flow.c index 2bfd081..53c6058 100644 --- a/net/core/flow.c @@ -87290,7 +87444,7 @@ index d9c4f11..02b82dbc 100644 msg.msg_flags = flags; diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c -index c3a4233..7df5626 100644 +index c3a4233..3fa029d 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -47,7 +47,7 @@ @@ -87312,7 +87466,25 @@ index c3a4233..7df5626 100644 skb_dst_drop(skb); skb_dst_set(skb, &rt->dst); nf_reset(skb); -@@ -886,7 +885,7 @@ static const struct nla_policy vti_policy[IFLA_VTI_MAX + 1] = { +@@ -645,17 +644,10 @@ static int __net_init vti_fb_tunnel_init(struct net_device *dev) + struct iphdr *iph = &tunnel->parms.iph; + struct vti_net *ipn = net_generic(dev_net(dev), vti_net_id); + +- tunnel->dev = dev; +- strcpy(tunnel->parms.name, dev->name); +- + iph->version = 4; + iph->protocol = IPPROTO_IPIP; + iph->ihl = 5; + +- dev->tstats = alloc_percpu(struct pcpu_tstats); +- if (!dev->tstats) +- return -ENOMEM; +- + dev_hold(dev); + rcu_assign_pointer(ipn->tunnels_wc[0], tunnel); + return 0; +@@ -886,7 +878,7 @@ static const struct nla_policy vti_policy[IFLA_VTI_MAX + 1] = { [IFLA_VTI_REMOTE] = { .len = FIELD_SIZEOF(struct iphdr, daddr) }, }; @@ -87916,7 +88088,7 @@ index b78aac3..e18230b 100644 syn_set ? 0 : icsk->icsk_user_timeout, syn_set)) { /* Has it gone just too far? */ diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c -index 0a073a2..ddf6279 100644 +index 0a073a2..d4a04de 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -87,6 +87,7 @@ @@ -87948,7 +88120,24 @@ index 0a073a2..ddf6279 100644 /* * This routine is called by the ICMP module when it gets some * sort of error condition. If err < 0 then the socket should -@@ -889,9 +897,18 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, +@@ -799,7 +807,7 @@ send: + /* + * Push out all pending data as one UDP datagram. Socket is locked. + */ +-static int udp_push_pending_frames(struct sock *sk) ++int udp_push_pending_frames(struct sock *sk) + { + struct udp_sock *up = udp_sk(sk); + struct inet_sock *inet = inet_sk(sk); +@@ -818,6 +826,7 @@ out: + up->pending = 0; + return err; + } ++EXPORT_SYMBOL(udp_push_pending_frames); + + int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +@@ -889,9 +898,18 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, dport = usin->sin_port; if (dport == 0) return -EINVAL; @@ -87967,7 +88156,7 @@ index 0a073a2..ddf6279 100644 daddr = inet->inet_daddr; dport = inet->inet_dport; /* Open fast path for connected socket. -@@ -1133,7 +1150,7 @@ static unsigned int first_packet_length(struct sock *sk) +@@ -1133,7 +1151,7 @@ static unsigned int first_packet_length(struct sock *sk) udp_lib_checksum_complete(skb)) { UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, IS_UDPLITE(sk)); @@ -87976,7 +88165,7 @@ index 0a073a2..ddf6279 100644 __skb_unlink(skb, rcvq); __skb_queue_tail(&list_kill, skb); } -@@ -1219,6 +1236,10 @@ try_again: +@@ -1219,6 +1237,10 @@ try_again: if (!skb) goto out; @@ -87987,7 +88176,7 @@ index 0a073a2..ddf6279 100644 ulen = skb->len - sizeof(struct udphdr); copied = len; if (copied > ulen) -@@ -1252,7 +1273,7 @@ try_again: +@@ -1252,7 +1274,7 @@ try_again: if (unlikely(err)) { trace_kfree_skb(skb, udp_recvmsg); if (!peeked) { @@ -87996,7 +88185,7 @@ index 0a073a2..ddf6279 100644 UDP_INC_STATS_USER(sock_net(sk), UDP_MIB_INERRORS, is_udplite); } -@@ -1535,7 +1556,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +@@ -1535,7 +1557,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) drop: UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); @@ -88005,7 +88194,7 @@ index 0a073a2..ddf6279 100644 kfree_skb(skb); return -1; } -@@ -1554,7 +1575,7 @@ static void flush_stack(struct sock **stack, unsigned int count, +@@ -1554,7 +1576,7 @@ static void flush_stack(struct sock **stack, unsigned int count, skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); if (!skb1) { @@ -88014,7 +88203,7 @@ index 0a073a2..ddf6279 100644 UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, -@@ -1723,6 +1744,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, +@@ -1723,6 +1745,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, goto csum_error; UDP_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); @@ -88024,7 +88213,7 @@ index 0a073a2..ddf6279 100644 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); /* -@@ -2152,7 +2176,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, +@@ -2152,7 +2177,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), 0, sock_i_ino(sp), atomic_read(&sp->sk_refcnt), sp, @@ -88116,6 +88305,53 @@ index fff5bdd..15194fb 100644 table = kmemdup(ipv6_icmp_table_template, sizeof(ipv6_icmp_table_template), +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index 192dd1a..5fc9c7a 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -632,6 +632,12 @@ insert_above: + return ln; + } + ++static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt) ++{ ++ return (rt->rt6i_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) == ++ RTF_GATEWAY; ++} ++ + /* + * Insert routing information in a node. + */ +@@ -646,6 +652,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + int add = (!info->nlh || + (info->nlh->nlmsg_flags & NLM_F_CREATE)); + int found = 0; ++ bool rt_can_ecmp = rt6_qualify_for_ecmp(rt); + + ins = &fn->leaf; + +@@ -691,9 +698,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + * To avoid long list, we only had siblings if the + * route have a gateway. + */ +- if (rt->rt6i_flags & RTF_GATEWAY && +- !(rt->rt6i_flags & RTF_EXPIRES) && +- !(iter->rt6i_flags & RTF_EXPIRES)) ++ if (rt_can_ecmp && ++ rt6_qualify_for_ecmp(iter)) + rt->rt6i_nsiblings++; + } + +@@ -715,7 +721,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, + /* Find the first route that have the same metric */ + sibling = fn->leaf; + while (sibling) { +- if (sibling->rt6i_metric == rt->rt6i_metric) { ++ if (sibling->rt6i_metric == rt->rt6i_metric && ++ rt6_qualify_for_ecmp(sibling)) { + list_add_tail(&rt->rt6i_siblings, + &sibling->rt6i_siblings); + break; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 95d13c7..791fe2f 100644 --- a/net/ipv6/ip6_gre.c @@ -88157,7 +88393,7 @@ index 95d13c7..791fe2f 100644 .maxtype = IFLA_GRE_MAX, .policy = ip6gre_policy, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c -index 851fdae..9d4d1fd 100644 +index 851fdae..8f6f09a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -822,11 +822,17 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, @@ -88179,6 +88415,56 @@ index 851fdae..9d4d1fd 100644 /* Yes, checking route validity in not connected * case is not very simple. Take into account, * that we do not support routing by source, TOS, +@@ -1093,11 +1099,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, + return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; + } + +-static void ip6_append_data_mtu(int *mtu, ++static void ip6_append_data_mtu(unsigned int *mtu, + int *maxfraglen, + unsigned int fragheaderlen, + struct sk_buff *skb, +- struct rt6_info *rt) ++ struct rt6_info *rt, ++ bool pmtuprobe) + { + if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { + if (skb == NULL) { +@@ -1109,7 +1116,9 @@ static void ip6_append_data_mtu(int *mtu, + * this fragment is not first, the headers + * space is regarded as data space. + */ +- *mtu = dst_mtu(rt->dst.path); ++ *mtu = min(*mtu, pmtuprobe ? ++ rt->dst.dev->mtu : ++ dst_mtu(rt->dst.path)); + } + *maxfraglen = ((*mtu - fragheaderlen) & ~7) + + fragheaderlen - sizeof(struct frag_hdr); +@@ -1126,11 +1135,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, + struct ipv6_pinfo *np = inet6_sk(sk); + struct inet_cork *cork; + struct sk_buff *skb, *skb_prev = NULL; +- unsigned int maxfraglen, fragheaderlen; ++ unsigned int maxfraglen, fragheaderlen, mtu; + int exthdrlen; + int dst_exthdrlen; + int hh_len; +- int mtu; + int copy; + int err; + int offset = 0; +@@ -1290,7 +1298,9 @@ alloc_new_skb: + /* update mtu and maxfraglen if necessary */ + if (skb == NULL || skb_prev == NULL) + ip6_append_data_mtu(&mtu, &maxfraglen, +- fragheaderlen, skb, rt); ++ fragheaderlen, skb, rt, ++ np->pmtudisc == ++ IPV6_PMTUDISC_PROBE); + + skb_prev = skb; + diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fff83cb..82d49dd 100644 --- a/net/ipv6/ip6_tunnel.c @@ -88539,7 +88825,7 @@ index 0fce928..c52a518 100644 } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c -index 27f0f8e..949e7ee 100644 +index 27f0f8e..a8928b5 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -52,6 +52,10 @@ @@ -88590,7 +88876,25 @@ index 27f0f8e..949e7ee 100644 icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); kfree_skb(skb); -@@ -1377,7 +1384,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket +@@ -945,11 +952,16 @@ static int udp_v6_push_pending_frames(struct sock *sk) + struct udphdr *uh; + struct udp_sock *up = udp_sk(sk); + struct inet_sock *inet = inet_sk(sk); +- struct flowi6 *fl6 = &inet->cork.fl.u.ip6; ++ struct flowi6 *fl6; + int err = 0; + int is_udplite = IS_UDPLITE(sk); + __wsum csum = 0; + ++ if (up->pending == AF_INET) ++ return udp_push_pending_frames(sk); ++ ++ fl6 = &inet->cork.fl.u.ip6; ++ + /* Grab the skbuff where UDP header space exists. */ + if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) + goto out; +@@ -1377,7 +1389,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket 0, sock_i_ino(sp), atomic_read(&sp->sk_refcnt), sp, @@ -88789,6 +89093,20 @@ index 5b1e5af..1b929e7 100644 } while (!res); return res; } +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 8dec687..5ebee2d 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -1793,7 +1793,8 @@ static const struct proto_ops pppol2tp_ops = { + + static const struct pppox_proto pppol2tp_proto = { + .create = pppol2tp_create, +- .ioctl = pppol2tp_ioctl ++ .ioctl = pppol2tp_ioctl, ++ .owner = THIS_MODULE, + }; + + #ifdef CONFIG_L2TP_V3 diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 843d8c4..cb04fa1 100644 --- a/net/mac80211/cfg.c @@ -90825,6 +91143,58 @@ index 8343737..677025e 100644 .mode = 0644, .proc_handler = read_reset_stat, }, +diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c +index 8d2eddd..65b1462 100644 +--- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c ++++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c +@@ -98,6 +98,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, + */ + static u32 *decode_write_list(u32 *va, u32 *vaend) + { ++ unsigned long start, end; + int nchunks; + + struct rpcrdma_write_array *ary = +@@ -113,9 +114,12 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) + return NULL; + } + nchunks = ntohl(ary->wc_nchunks); +- if (((unsigned long)&ary->wc_array[0] + +- (sizeof(struct rpcrdma_write_chunk) * nchunks)) > +- (unsigned long)vaend) { ++ ++ start = (unsigned long)&ary->wc_array[0]; ++ end = (unsigned long)vaend; ++ if (nchunks < 0 || ++ nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) || ++ (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) { + dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", + ary, nchunks, vaend); + return NULL; +@@ -129,6 +133,7 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) + + static u32 *decode_reply_array(u32 *va, u32 *vaend) + { ++ unsigned long start, end; + int nchunks; + struct rpcrdma_write_array *ary = + (struct rpcrdma_write_array *)va; +@@ -143,9 +148,12 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend) + return NULL; + } + nchunks = ntohl(ary->wc_nchunks); +- if (((unsigned long)&ary->wc_array[0] + +- (sizeof(struct rpcrdma_write_chunk) * nchunks)) > +- (unsigned long)vaend) { ++ ++ start = (unsigned long)&ary->wc_array[0]; ++ end = (unsigned long)vaend; ++ if (nchunks < 0 || ++ nchunks > (SIZE_MAX - start) / sizeof(struct rpcrdma_write_chunk) || ++ (start + (sizeof(struct rpcrdma_write_chunk) * nchunks)) > end) { + dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", + ary, nchunks, vaend); + return NULL; diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 0ce7552..d074459 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c |