Linux v3.13.10

This commit is contained in:
Justin M. Forbes 2014-04-14 15:12:54 -05:00
parent e906b02d91
commit 90af1aa03b
10 changed files with 5 additions and 981 deletions

View File

@ -1,32 +0,0 @@
Bugzilla: 1074471
Upstream-status: queued for 3.14
From c88507fbad8055297c1d1e21e599f46960cbee39 Mon Sep 17 00:00:00 2001
From: Sabrina Dubroca <sd@queasysnail.net>
Date: Thu, 06 Mar 2014 16:51:57 +0000
Subject: ipv6: don't set DST_NOCOUNT for remotely added routes
DST_NOCOUNT should only be used if an authorized user adds routes
locally. In case of routes which are added on behalf of router
advertisments this flag must not get used as it allows an unlimited
number of routes getting added remotely.
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 11dac21..fba54a4 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1513,7 +1513,7 @@ int ip6_route_add(struct fib6_config *cfg)
if (!table)
goto out;
- rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table);
+ rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table);
if (!rt) {
err = -ENOMEM;
--
cgit v0.9.2

View File

@ -74,7 +74,7 @@ Summary: The Linux kernel
%if 0%{?released_kernel}
# Do we have a -stable update to apply?
%define stable_update 9
%define stable_update 10
# Is it a -stable RC?
%define stable_rc 0
# Set rpm version accordingly
@ -735,9 +735,6 @@ Patch25026: keyring-fix.patch
#rhbz 1065087
Patch25028: tty-Fix-low_latency-BUG.patch
#CVE-2014-0100 rhbz 1072026 1070618
Patch25031: net-fix-for-a-race-condition-in-the-inet-frag-code.patch
#rhbz 1027465
Patch25032: HID-Bluetooth-hidp-make-sure-input-buffers-are-big-e.patch
@ -750,36 +747,15 @@ Patch25035: Bluetooth-allocate-static-minor-for-vhci.patch
#rhbz 1065663
Patch25040: iwlwifi-dvm-clear-IWL_STA_UCODE_INPROGRESS-when-asso.patch
#CVE-2014-2309 rhbz 1074471 1075064
Patch25041: ipv6-dont-set-DST_NOCOUNT-for-remotely-added-routes.patch
#rhbz 1046495
Patch25044: iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
#CVE-2014-0131 rhbz 1074589 1079006
Patch25048: skbuff-zero-copy.patch
#CVE-2014-2568 rhbz 1079012 1079013
Patch25049: nfqueue-Orphan-frags-in-nfqnl_zcopy-and-handle-error.patch
#CVE-2014-0055 rhbz 1062577 1081503
Patch25050: net-vhost-validate-vhost_get_vq_desc-return-value.patch
#CVE-2014-0077 rhbz 1064440 1081504
Patch25051: net-vhost-fix-total-length-when-packets-are-too-short.patch
#CVE-2014-2580 rhbz 1080084 1080086
Patch25052: net-xen-netback-disable-rogue-vif-in-kthread-context.patch
#CVE-2014-2678 rhbz 1083274 1083280
Patch25054: rds-prevent-dereference-of-a-NULL-device-in-rds_iw_laddr_check.patch
#rhbz 1074235
Patch25055: lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch
#rhbz 1084829
Patch25056: selinux-correctly-label-proc-inodes-in-use-before-th.patch
#CVE-2014-0155 rhbz 1081589 1085016
Patch25057: KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch
@ -1483,9 +1459,6 @@ ApplyPatch keyring-fix.patch
#rhbz 1065087
ApplyPatch tty-Fix-low_latency-BUG.patch
#CVE-2014-0100 rhbz 1072026 1070618
ApplyPatch net-fix-for-a-race-condition-in-the-inet-frag-code.patch
#rhbz 1027465
ApplyPatch HID-Bluetooth-hidp-make-sure-input-buffers-are-big-e.patch
@ -1498,36 +1471,15 @@ ApplyPatch Bluetooth-allocate-static-minor-for-vhci.patch
#rhbz 1065663
ApplyPatch iwlwifi-dvm-clear-IWL_STA_UCODE_INPROGRESS-when-asso.patch
#CVE-2014-2309 rhbz 1074471 1075064
ApplyPatch ipv6-dont-set-DST_NOCOUNT-for-remotely-added-routes.patch
#rhbz 1046495
ApplyPatch iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
#CVE-2014-0131 rhbz 1074589 1079006
ApplyPatch skbuff-zero-copy.patch
#CVE-2014-2568 rhbz 1079012 1079013
ApplyPatch nfqueue-Orphan-frags-in-nfqnl_zcopy-and-handle-error.patch
#CVE-2014-0055 rhbz 1062577 1081503
ApplyPatch net-vhost-validate-vhost_get_vq_desc-return-value.patch
#CVE-2014-0077 rhbz 1064440 1081504
ApplyPatch net-vhost-fix-total-length-when-packets-are-too-short.patch
#CVE-2014-2580 rhbz 1080084 1080086
ApplyPatch net-xen-netback-disable-rogue-vif-in-kthread-context.patch
#CVE-2014-2678 rhbz 1083274 1083280
ApplyPatch rds-prevent-dereference-of-a-NULL-device-in-rds_iw_laddr_check.patch
#rhbz 1074235
ApplyPatch lib-percpu_counter.c-fix-bad-percpu-counter-state-du.patch
#rhbz 1084829
ApplyPatch selinux-correctly-label-proc-inodes-in-use-before-th.patch
#CVE-2014-0155 rhbz 1081589 1085016
ApplyPatch KVM-ioapic-fix-assignment-of-ioapic-rtc_status-pending_eoi.patch
@ -2351,6 +2303,9 @@ fi
# ||----w |
# || ||
%changelog
* Mon Apr 14 2014 Justin M. Forbes <jforbes@fedoraproject.org> - 3.13.10-200
- Linux v3.13.10
* Mon Apr 14 2014 Hans de Goede <hdegoede@redhat.com>
- Add min/max quirks for various new Thinkpad touchpads (rhbz 1085582 1085697)

View File

@ -1,19 +0,0 @@
Bugzilla: 1070618
Upstream-status: submitted http://patchwork.ozlabs.org/patch/325844/
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index bb075fc9a14f..322dcebfc588 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -278,9 +278,10 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf,
atomic_inc(&qp->refcnt);
hlist_add_head(&qp->list, &hb->chain);
+ inet_frag_lru_add(nf, qp);
spin_unlock(&hb->chain_lock);
read_unlock(&f->lock);
- inet_frag_lru_add(nf, qp);
+
return qp;
}

View File

@ -1,80 +0,0 @@
Bugzilla: 1081504
Upstream-status: Sent to netdev list
From patchwork Thu Mar 27 10:00:26 2014
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCHv2,net] vhost: fix total length when packets are too short
From: "Michael S. Tsirkin" <mst@redhat.com>
X-Patchwork-Id: 334283
Message-Id: <20140327100026.GA30715@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org, virtio-dev@lists.oasis-open.org,
virtualization@lists.linux-foundation.org, netdev@vger.kernel.org,
Jason Wang <jasowang@redhat.com>, David Miller <davem@davemloft.net>
Date: Thu, 27 Mar 2014 12:00:26 +0200
When mergeable buffers are disabled, and the
incoming packet is too large for the rx buffer,
get_rx_bufs returns success.
This was intentional in order for make recvmsg
truncate the packet and then handle_rx would
detect err != sock_len and drop it.
Unfortunately we pass the original sock_len to
recvmsg - which means we use parts of iov not fully
validated.
Fix this up by detecting this overrun and doing packet drop
immediately.
CVE-2014-0077
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Changes from v1:
Fix CVE# in the commit log.
Patch is unchanged.
Note: this is needed for -stable.
I wonder if this can still make the release.
drivers/vhost/net.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index a0fa5de..026be58 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -532,6 +532,12 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
*iovcount = seg;
if (unlikely(log))
*log_num = nlogs;
+
+ /* Detect overrun */
+ if (unlikely(datalen > 0)) {
+ r = UIO_MAXIOV + 1;
+ goto err;
+ }
return headcount;
err:
vhost_discard_vq_desc(vq, headcount);
@@ -587,6 +593,14 @@ static void handle_rx(struct vhost_net *net)
/* On error, stop handling until the next kick. */
if (unlikely(headcount < 0))
break;
+ /* On overrun, truncate and discard */
+ if (unlikely(headcount > UIO_MAXIOV)) {
+ msg.msg_iovlen = 1;
+ err = sock->ops->recvmsg(NULL, sock, &msg,
+ 1, MSG_DONTWAIT | MSG_TRUNC);
+ pr_debug("Discarded rx packet: len %zd\n", sock_len);
+ continue;
+ }
/* OK, now we need to know about added descriptors. */
if (!headcount) {
if (unlikely(vhost_enable_notify(&net->dev, vq))) {

View File

@ -1,55 +0,0 @@
Bugzilla: 1081503
Upstream-status: Sent to netdev
From patchwork Thu Mar 27 10:53:37 2014
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [net] vhost: validate vhost_get_vq_desc return value
From: "Michael S. Tsirkin" <mst@redhat.com>
X-Patchwork-Id: 334291
Message-Id: <1395917517-30937-1-git-send-email-mst@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org, virtio-dev@lists.oasis-open.org,
virtualization@lists.linux-foundation.org, netdev@vger.kernel.org,
David Miller <davem@davemloft.net>, Jason Wang <jasowang@redhat.com>
Date: Thu, 27 Mar 2014 12:53:37 +0200
vhost fails to validate negative error code
from vhost_get_vq_desc causing
a crash: we are using -EFAULT which is 0xfffffff2
as vector size, which exceeds the allocated size.
The code in question was introduced in commit
8dd014adfea6f173c1ef6378f7e5e7924866c923
vhost-net: mergeable buffers support
CVE-2014-0055
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
This is needed in -stable.
drivers/vhost/net.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 026be58..e1e22e0 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -505,9 +505,13 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
r = -ENOBUFS;
goto err;
}
- d = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
+ r = vhost_get_vq_desc(vq->dev, vq, vq->iov + seg,
ARRAY_SIZE(vq->iov) - seg, &out,
&in, log, log_num);
+ if (unlikely(r < 0))
+ goto err;
+
+ d = r;
if (d == vq->num) {
r = 0;
goto err;

View File

@ -1,143 +0,0 @@
Bugzilla: 1080086
Upstream-status: sent to netdev list
From patchwork Tue Mar 25 12:20:51 2014
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Subject: [net,V2] xen-netback: disable rogue vif in kthread context
From: Wei Liu <wei.liu2@citrix.com>
X-Patchwork-Id: 333459
Message-Id: <1395750051-15932-1-git-send-email-wei.liu2@citrix.com>
To: <netdev@vger.kernel.org>, <xen-devel@lists.xen.org>
Cc: <paul.durrant@citrix.com>, <zoltan.kiss@citrix.com>,
<edwin@etorok.net>, <david.vrabel@citrix.com>,
Wei Liu <wei.liu2@citrix.com>, Ian Campbell <ian.campbell@citrix.com>
Date: Tue, 25 Mar 2014 12:20:51 +0000
When netback discovers frontend is sending malformed packet it will
disables the interface which serves that frontend.
However disabling a network interface involving taking a mutex which
cannot be done in softirq context, so we need to defer this process to
kthread context.
This patch does the following:
1. introduce a flag to indicate the interface is disabled.
2. check that flag in TX path, don't do any work if it's true.
3. check that flag in RX path, turn off that interface if it's true.
The reason to disable it in RX path is because RX uses kthread. After
this change the behavior of netback is still consistent -- it won't do
any TX work for a rogue frontend, and the interface will be eventually
turned off.
Also change a "continue" to "break" after xenvif_fatal_tx_err, as it
doesn't make sense to continue processing packets if frontend is rogue.
This is a fix for XSA-90.
Reported-by: Török Edwin <edwin@etorok.net>
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>
---
drivers/net/xen-netback/common.h | 5 +++++
drivers/net/xen-netback/interface.c | 15 ++++++++++++++-
drivers/net/xen-netback/netback.c | 15 +++++++++++++--
3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index ae413a2..4bf5b33 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -113,6 +113,11 @@ struct xenvif {
domid_t domid;
unsigned int handle;
+ /* Is this interface disabled? True when backend discovers
+ * frontend is rogue.
+ */
+ bool disabled;
+
/* Use NAPI for guest TX */
struct napi_struct napi;
/* When feature-split-event-channels = 0, tx_irq = rx_irq. */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 301cc03..8c921de 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -61,12 +61,23 @@ static int xenvif_poll(struct napi_struct *napi, int budget)
{
struct xenvif *vif = container_of(napi, struct xenvif, napi);
int work_done;
+ unsigned long flags;
+
+ /* This vif is rogue, we pretend we've there is nothing to do
+ * for this vif to deschedule it from NAPI. But this interface
+ * will be turned off in thread context later.
+ */
+ if (unlikely(vif->disabled)) {
+ local_irq_save(flags);
+ __napi_complete(napi);
+ local_irq_restore(flags);
+ return 0;
+ }
work_done = xenvif_tx_action(vif, budget);
if (work_done < budget) {
int more_to_do = 0;
- unsigned long flags;
/* It is necessary to disable IRQ before calling
* RING_HAS_UNCONSUMED_REQUESTS. Otherwise we might
@@ -321,6 +332,8 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
vif->ip_csum = 1;
vif->dev = dev;
+ vif->disabled = false;
+
vif->credit_bytes = vif->remaining_credit = ~0UL;
vif->credit_usec = 0UL;
init_timer(&vif->credit_timeout);
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 438d0c0..17633dd 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -655,7 +655,8 @@ static void xenvif_tx_err(struct xenvif *vif,
static void xenvif_fatal_tx_err(struct xenvif *vif)
{
netdev_err(vif->dev, "fatal error; disabling device\n");
- xenvif_carrier_off(vif);
+ vif->disabled = true;
+ xenvif_kick_thread(vif);
}
static int xenvif_count_requests(struct xenvif *vif,
@@ -1126,7 +1127,7 @@ static unsigned xenvif_tx_build_gops(struct xenvif *vif, int budget)
vif->tx.sring->req_prod, vif->tx.req_cons,
XEN_NETIF_TX_RING_SIZE);
xenvif_fatal_tx_err(vif);
- continue;
+ break;
}
work_to_do = RING_HAS_UNCONSUMED_REQUESTS(&vif->tx);
@@ -1549,6 +1550,16 @@ int xenvif_kthread(void *data)
wait_event_interruptible(vif->wq,
rx_work_todo(vif) ||
kthread_should_stop());
+
+ /* This frontend is found to be rogue, disable it in
+ * kthread context. Currently this is only set when
+ * netback finds out frontend sends malformed packet,
+ * but we cannot disable the interface in softirq
+ * context so we defer it here.
+ */
+ if (unlikely(vif->disabled && netif_carrier_ok(vif->dev)))
+ xenvif_carrier_off(vif);
+
if (kthread_should_stop())
break;

View File

@ -1,31 +0,0 @@
Bugzilla: 1083280
Upstream-status: Queued for 3.15
From bf39b4247b8799935ea91d90db250ab608a58e50 Mon Sep 17 00:00:00 2001
From: Sasha Levin <sasha.levin@oracle.com>
Date: Sat, 29 Mar 2014 20:39:35 -0400
Subject: rds: prevent dereference of a NULL device in rds_iw_laddr_check
Binding might result in a NULL device which is later dereferenced
without checking.
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/rds/iw.c b/net/rds/iw.c
index 7826d46..5899356 100644
--- a/net/rds/iw.c
+++ b/net/rds/iw.c
@@ -239,7 +239,8 @@ static int rds_iw_laddr_check(__be32 addr)
ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin);
/* due to this, we will claim to support IB devices unless we
check node_type. */
- if (ret || cm_id->device->node_type != RDMA_NODE_RNIC)
+ if (ret || !cm_id->device ||
+ cm_id->device->node_type != RDMA_NODE_RNIC)
ret = -EADDRNOTAVAIL;
rdsdebug("addr %pI4 ret %d node type %d\n",
--
cgit v0.10.1

View File

@ -1,109 +0,0 @@
Bugzilla: 1084829
Upstream-status: 3.15 (needs to be on 3.13 and 3.14)
From f64410ec665479d7b4b77b7519e814253ed0f686 Mon Sep 17 00:00:00 2001
From: Paul Moore <pmoore@redhat.com>
Date: Wed, 19 Mar 2014 16:46:18 -0400
Subject: [PATCH] selinux: correctly label /proc inodes in use before the
policy is loaded
This patch is based on an earlier patch by Eric Paris, he describes
the problem below:
"If an inode is accessed before policy load it will get placed on a
list of inodes to be initialized after policy load. After policy
load we call inode_doinit() which calls inode_doinit_with_dentry()
on all inodes accessed before policy load. In the case of inodes
in procfs that means we'll end up at the bottom where it does:
/* Default to the fs superblock SID. */
isec->sid = sbsec->sid;
if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
if (opt_dentry) {
isec->sclass = inode_mode_to_security_class(...)
rc = selinux_proc_get_sid(opt_dentry,
isec->sclass,
&sid);
if (rc)
goto out_unlock;
isec->sid = sid;
}
}
Since opt_dentry is null, we'll never call selinux_proc_get_sid()
and will leave the inode labeled with the label on the superblock.
I believe a fix would be to mimic the behavior of xattrs. Look
for an alias of the inode. If it can't be found, just leave the
inode uninitialized (and pick it up later) if it can be found, we
should be able to call selinux_proc_get_sid() ..."
On a system exhibiting this problem, you will notice a lot of files in
/proc with the generic "proc_t" type (at least the ones that were
accessed early in the boot), for example:
# ls -Z /proc/sys/kernel/shmmax | awk '{ print $4 " " $5 }'
system_u:object_r:proc_t:s0 /proc/sys/kernel/shmmax
However, with this patch in place we see the expected result:
# ls -Z /proc/sys/kernel/shmmax | awk '{ print $4 " " $5 }'
system_u:object_r:sysctl_kernel_t:s0 /proc/sys/kernel/shmmax
Cc: Eric Paris <eparis@redhat.com>
Signed-off-by: Paul Moore <pmoore@redhat.com>
Acked-by: Eric Paris <eparis@redhat.com>
---
security/selinux/hooks.c | 36 +++++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1dd948485e48..d5d67c93b65c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1402,15 +1402,33 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
isec->sid = sbsec->sid;
if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
- if (opt_dentry) {
- isec->sclass = inode_mode_to_security_class(inode->i_mode);
- rc = selinux_proc_get_sid(opt_dentry,
- isec->sclass,
- &sid);
- if (rc)
- goto out_unlock;
- isec->sid = sid;
- }
+ /* We must have a dentry to determine the label on
+ * procfs inodes */
+ if (opt_dentry)
+ /* Called from d_instantiate or
+ * d_splice_alias. */
+ dentry = dget(opt_dentry);
+ else
+ /* Called from selinux_complete_init, try to
+ * find a dentry. */
+ dentry = d_find_alias(inode);
+ /*
+ * This can be hit on boot when a file is accessed
+ * before the policy is loaded. When we load policy we
+ * may find inodes that have no dentry on the
+ * sbsec->isec_head list. No reason to complain as
+ * these will get fixed up the next time we go through
+ * inode_doinit() with a dentry, before these inodes
+ * could be used again by userspace.
+ */
+ if (!dentry)
+ goto out_unlock;
+ isec->sclass = inode_mode_to_security_class(inode->i_mode);
+ rc = selinux_proc_get_sid(dentry, isec->sclass, &sid);
+ dput(dentry);
+ if (rc)
+ goto out_unlock;
+ isec->sid = sid;
}
break;
}
--
1.8.5.3

View File

@ -1,462 +0,0 @@
Bugzilla: 1079006
Upstream-status: 3.14 and queued for stable
From 8cb19905e9287a93ce7c2cbbdf742a060b00e219 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 10 Mar 2014 18:29:04 +0200
Subject: [PATCH 1/5] skbuff: skb_segment: s/frag/nskb_frag/
frag points at nskb, so name it appropriately
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/core/skbuff.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5d6236d..60e8cd7 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2876,7 +2876,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
do {
struct sk_buff *nskb;
- skb_frag_t *frag;
+ skb_frag_t *nskb_frag;
int hsize;
int size;
@@ -2969,7 +2969,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
continue;
}
- frag = skb_shinfo(nskb)->frags;
+ nskb_frag = skb_shinfo(nskb)->frags;
skb_copy_from_linear_data_offset(skb, offset,
skb_put(nskb, hsize), hsize);
@@ -2997,13 +2997,13 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
goto err;
}
- *frag = *skb_frag;
- __skb_frag_ref(frag);
- size = skb_frag_size(frag);
+ *nskb_frag = *skb_frag;
+ __skb_frag_ref(nskb_frag);
+ size = skb_frag_size(nskb_frag);
if (pos < offset) {
- frag->page_offset += offset - pos;
- skb_frag_size_sub(frag, offset - pos);
+ nskb_frag->page_offset += offset - pos;
+ skb_frag_size_sub(nskb_frag, offset - pos);
}
skb_shinfo(nskb)->nr_frags++;
@@ -3013,11 +3013,11 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
skb_frag++;
pos += size;
} else {
- skb_frag_size_sub(frag, pos + size - (offset + len));
+ skb_frag_size_sub(nskb_frag, pos + size - (offset + len));
goto skip_fraglist;
}
- frag++;
+ nskb_frag++;
}
skip_fraglist:
--
1.8.5.3
From 4e1beba12d094c6c761ba5c49032b9b9e46380e8 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 10 Mar 2014 18:29:14 +0200
Subject: [PATCH 2/5] skbuff: skb_segment: s/skb_frag/frag/
skb_frag can in fact point at either skb
or fskb so rename it generally "frag".
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/core/skbuff.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 60e8cd7..d788a98 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2850,7 +2850,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
struct sk_buff *segs = NULL;
struct sk_buff *tail = NULL;
struct sk_buff *fskb = skb_shinfo(skb)->frag_list;
- skb_frag_t *skb_frag = skb_shinfo(skb)->frags;
+ skb_frag_t *frag = skb_shinfo(skb)->frags;
unsigned int mss = skb_shinfo(skb)->gso_size;
unsigned int doffset = skb->data - skb_mac_header(skb);
unsigned int offset = doffset;
@@ -2896,19 +2896,19 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
i = 0;
nfrags = skb_shinfo(fskb)->nr_frags;
- skb_frag = skb_shinfo(fskb)->frags;
+ frag = skb_shinfo(fskb)->frags;
pos += skb_headlen(fskb);
while (pos < offset + len) {
BUG_ON(i >= nfrags);
- size = skb_frag_size(skb_frag);
+ size = skb_frag_size(frag);
if (pos + size > offset + len)
break;
i++;
pos += size;
- skb_frag++;
+ frag++;
}
nskb = skb_clone(fskb, GFP_ATOMIC);
@@ -2982,7 +2982,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
i = 0;
nfrags = skb_shinfo(fskb)->nr_frags;
- skb_frag = skb_shinfo(fskb)->frags;
+ frag = skb_shinfo(fskb)->frags;
BUG_ON(!nfrags);
@@ -2997,7 +2997,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
goto err;
}
- *nskb_frag = *skb_frag;
+ *nskb_frag = *frag;
__skb_frag_ref(nskb_frag);
size = skb_frag_size(nskb_frag);
@@ -3010,7 +3010,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
if (pos + size <= offset + len) {
i++;
- skb_frag++;
+ frag++;
pos += size;
} else {
skb_frag_size_sub(nskb_frag, pos + size - (offset + len));
--
1.8.5.3
From df5771ffefb13f8af5392bd54fd7e2b596a3a357 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 10 Mar 2014 18:29:19 +0200
Subject: [PATCH 3/5] skbuff: skb_segment: s/skb/head_skb/
rename local variable to make it easier to tell at a glance that we are
dealing with a head skb.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/core/skbuff.c | 46 ++++++++++++++++++++++++----------------------
1 file changed, 24 insertions(+), 22 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d788a98..fdc065d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2838,41 +2838,42 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum);
/**
* skb_segment - Perform protocol segmentation on skb.
- * @skb: buffer to segment
+ * @head_skb: buffer to segment
* @features: features for the output path (see dev->features)
*
* This function performs segmentation on the given skb. It returns
* a pointer to the first in a list of new skbs for the segments.
* In case of error it returns ERR_PTR(err).
*/
-struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
+struct sk_buff *skb_segment(struct sk_buff *head_skb,
+ netdev_features_t features)
{
struct sk_buff *segs = NULL;
struct sk_buff *tail = NULL;
- struct sk_buff *fskb = skb_shinfo(skb)->frag_list;
- skb_frag_t *frag = skb_shinfo(skb)->frags;
- unsigned int mss = skb_shinfo(skb)->gso_size;
- unsigned int doffset = skb->data - skb_mac_header(skb);
+ struct sk_buff *fskb = skb_shinfo(head_skb)->frag_list;
+ skb_frag_t *frag = skb_shinfo(head_skb)->frags;
+ unsigned int mss = skb_shinfo(head_skb)->gso_size;
+ unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
unsigned int offset = doffset;
- unsigned int tnl_hlen = skb_tnl_header_len(skb);
+ unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
unsigned int headroom;
unsigned int len;
__be16 proto;
bool csum;
int sg = !!(features & NETIF_F_SG);
- int nfrags = skb_shinfo(skb)->nr_frags;
+ int nfrags = skb_shinfo(head_skb)->nr_frags;
int err = -ENOMEM;
int i = 0;
int pos;
- proto = skb_network_protocol(skb);
+ proto = skb_network_protocol(head_skb);
if (unlikely(!proto))
return ERR_PTR(-EINVAL);
csum = !!can_checksum_protocol(features, proto);
- __skb_push(skb, doffset);
- headroom = skb_headroom(skb);
- pos = skb_headlen(skb);
+ __skb_push(head_skb, doffset);
+ headroom = skb_headroom(head_skb);
+ pos = skb_headlen(head_skb);
do {
struct sk_buff *nskb;
@@ -2880,11 +2881,11 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
int hsize;
int size;
- len = skb->len - offset;
+ len = head_skb->len - offset;
if (len > mss)
len = mss;
- hsize = skb_headlen(skb) - offset;
+ hsize = skb_headlen(head_skb) - offset;
if (hsize < 0)
hsize = 0;
if (hsize > len || !sg)
@@ -2933,7 +2934,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
__skb_push(nskb, doffset);
} else {
nskb = __alloc_skb(hsize + doffset + headroom,
- GFP_ATOMIC, skb_alloc_rx_flag(skb),
+ GFP_ATOMIC, skb_alloc_rx_flag(head_skb),
NUMA_NO_NODE);
if (unlikely(!nskb))
@@ -2949,12 +2950,12 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
segs = nskb;
tail = nskb;
- __copy_skb_header(nskb, skb);
- nskb->mac_len = skb->mac_len;
+ __copy_skb_header(nskb, head_skb);
+ nskb->mac_len = head_skb->mac_len;
skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom);
- skb_copy_from_linear_data_offset(skb, -tnl_hlen,
+ skb_copy_from_linear_data_offset(head_skb, -tnl_hlen,
nskb->data - tnl_hlen,
doffset + tnl_hlen);
@@ -2963,7 +2964,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
if (!sg) {
nskb->ip_summed = CHECKSUM_NONE;
- nskb->csum = skb_copy_and_csum_bits(skb, offset,
+ nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
skb_put(nskb, len),
len, 0);
continue;
@@ -2971,10 +2972,11 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
nskb_frag = skb_shinfo(nskb)->frags;
- skb_copy_from_linear_data_offset(skb, offset,
+ skb_copy_from_linear_data_offset(head_skb, offset,
skb_put(nskb, hsize), hsize);
- skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
+ skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags &
+ SKBTX_SHARED_FRAG;
while (pos < offset + len) {
if (i >= nfrags) {
@@ -3031,7 +3033,7 @@ perform_csum_check:
nskb->len - doffset, 0);
nskb->ip_summed = CHECKSUM_NONE;
}
- } while ((offset += len) < skb->len);
+ } while ((offset += len) < head_skb->len);
return segs;
--
1.8.5.3
From 1a4cedaf65491e66e1e55b8428c89209da729209 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 10 Mar 2014 19:27:59 +0200
Subject: [PATCH 4/5] skbuff: skb_segment: s/fskb/list_skb/
fskb is unrelated to frag: it's coming from
frag_list. Rename it list_skb to avoid confusion.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/core/skbuff.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fdc065d..dc4f768 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2850,7 +2850,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
{
struct sk_buff *segs = NULL;
struct sk_buff *tail = NULL;
- struct sk_buff *fskb = skb_shinfo(head_skb)->frag_list;
+ struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list;
skb_frag_t *frag = skb_shinfo(head_skb)->frags;
unsigned int mss = skb_shinfo(head_skb)->gso_size;
unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
@@ -2891,14 +2891,14 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
if (hsize > len || !sg)
hsize = len;
- if (!hsize && i >= nfrags && skb_headlen(fskb) &&
- (skb_headlen(fskb) == len || sg)) {
- BUG_ON(skb_headlen(fskb) > len);
+ if (!hsize && i >= nfrags && skb_headlen(list_skb) &&
+ (skb_headlen(list_skb) == len || sg)) {
+ BUG_ON(skb_headlen(list_skb) > len);
i = 0;
- nfrags = skb_shinfo(fskb)->nr_frags;
- frag = skb_shinfo(fskb)->frags;
- pos += skb_headlen(fskb);
+ nfrags = skb_shinfo(list_skb)->nr_frags;
+ frag = skb_shinfo(list_skb)->frags;
+ pos += skb_headlen(list_skb);
while (pos < offset + len) {
BUG_ON(i >= nfrags);
@@ -2912,8 +2912,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
frag++;
}
- nskb = skb_clone(fskb, GFP_ATOMIC);
- fskb = fskb->next;
+ nskb = skb_clone(list_skb, GFP_ATOMIC);
+ list_skb = list_skb->next;
if (unlikely(!nskb))
goto err;
@@ -2980,15 +2980,15 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
while (pos < offset + len) {
if (i >= nfrags) {
- BUG_ON(skb_headlen(fskb));
+ BUG_ON(skb_headlen(list_skb));
i = 0;
- nfrags = skb_shinfo(fskb)->nr_frags;
- frag = skb_shinfo(fskb)->frags;
+ nfrags = skb_shinfo(list_skb)->nr_frags;
+ frag = skb_shinfo(list_skb)->frags;
BUG_ON(!nfrags);
- fskb = fskb->next;
+ list_skb = list_skb->next;
}
if (unlikely(skb_shinfo(nskb)->nr_frags >=
--
1.8.5.3
From 1fd819ecb90cc9b822cd84d3056ddba315d3340f Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Mon, 10 Mar 2014 19:28:08 +0200
Subject: [PATCH 5/5] skbuff: skb_segment: orphan frags before copying
skb_segment copies frags around, so we need
to copy them carefully to avoid accessing
user memory after reporting completion to userspace
through a callback.
skb_segment doesn't normally happen on datapath:
TSO needs to be disabled - so disabling zero copy
in this case does not look like a big deal.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
net/core/skbuff.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index dc4f768..869c7af 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2854,6 +2854,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
skb_frag_t *frag = skb_shinfo(head_skb)->frags;
unsigned int mss = skb_shinfo(head_skb)->gso_size;
unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
+ struct sk_buff *frag_skb = head_skb;
unsigned int offset = doffset;
unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
unsigned int headroom;
@@ -2898,6 +2899,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
i = 0;
nfrags = skb_shinfo(list_skb)->nr_frags;
frag = skb_shinfo(list_skb)->frags;
+ frag_skb = list_skb;
pos += skb_headlen(list_skb);
while (pos < offset + len) {
@@ -2985,6 +2987,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
i = 0;
nfrags = skb_shinfo(list_skb)->nr_frags;
frag = skb_shinfo(list_skb)->frags;
+ frag_skb = list_skb;
BUG_ON(!nfrags);
@@ -2999,6 +3002,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
goto err;
}
+ if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC)))
+ goto err;
+
*nskb_frag = *frag;
__skb_frag_ref(nskb_frag);
size = skb_frag_size(nskb_frag);
@@ -3081,10 +3081,7 @@ perform_csum_check:
return segs;
err:
- while ((skb = segs)) {
- segs = skb->next;
- kfree_skb(skb);
- }
+ kfree_skb_list(segs);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(skb_segment);
--
1.8.5.3

View File

@ -1,2 +1,2 @@
0ecbaf65c00374eb4a826c2f9f37606f linux-3.13.tar.xz
d1b35dfc218d54e6a443bb5fe22d5a7b patch-3.13.9.xz
dcf42b5013a7831d02168fd3eda5cce2 patch-3.13.10.xz