Commit 2090f6be authored by Natanael Copa's avatar Natanael Copa

main/linux-grsec: various security fixes (CVE-2013-4125, CVE-2013-4127)

ref #2139 (CVE-2013-4125)
ref #2144 (CVE-2013-4127)
parent 2f83f79d
......@@ -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
......
......@@ -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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment