summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@redhat.com>2014-03-28 11:04:39 -0400
committerJosh Boyer <jwboyer@redhat.com>2014-03-28 11:10:24 -0400
commit0fc5fab4f779681b264247626aa10004858ad556 (patch)
tree7eeac8af0682553681218228ca5b0b0d7c44b3f2
parent10f10342513a58e56b6cec54179b53499a01a00c (diff)
downloadkernel-0fc5fab4f779681b264247626aa10004858ad556.tar.gz
kernel-0fc5fab4f779681b264247626aa10004858ad556.tar.xz
kernel-0fc5fab4f779681b264247626aa10004858ad556.zip
CVE-2014-2568 net: potential info leak when ubuf backed skbs are zero copied (rhbz 1079012 1079013)
-rw-r--r--core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch163
-rw-r--r--kernel.spec9
2 files changed, 172 insertions, 0 deletions
diff --git a/core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch b/core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch
new file mode 100644
index 000000000..804f3a901
--- /dev/null
+++ b/core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch
@@ -0,0 +1,163 @@
+Bugzilla: 1079013
+Upstream-status: Queued in netdev tree
+
+From 36d5fe6a000790f56039afe26834265db0a3ad4c Mon Sep 17 00:00:00 2001
+From: Zoltan Kiss <zoltan.kiss@citrix.com>
+Date: Wed, 26 Mar 2014 22:37:45 +0000
+Subject: core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle
+ errors
+
+skb_zerocopy can copy elements of the frags array between skbs, but it doesn't
+orphan them. Also, it doesn't handle errors, so this patch takes care of that
+as well, and modify the callers accordingly. skb_tx_error() is also added to
+the callers so they will signal the failed delivery towards the creator of the
+skb.
+
+Signed-off-by: Zoltan Kiss <zoltan.kiss@citrix.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 5e1e6f2..15ede6a 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -2451,8 +2451,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
+ unsigned int flags);
+ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
+ unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
+-void skb_zerocopy(struct sk_buff *to, const struct sk_buff *from,
+- int len, int hlen);
++int skb_zerocopy(struct sk_buff *to, struct sk_buff *from,
++ int len, int hlen);
+ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
+ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
+ void skb_scrub_packet(struct sk_buff *skb, bool xnet);
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 869c7af..97e5a2c 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -2127,25 +2127,31 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
+ *
+ * The `hlen` as calculated by skb_zerocopy_headlen() specifies the
+ * headroom in the `to` buffer.
++ *
++ * Return value:
++ * 0: everything is OK
++ * -ENOMEM: couldn't orphan frags of @from due to lack of memory
++ * -EFAULT: skb_copy_bits() found some problem with skb geometry
+ */
+-void
+-skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
++int
++skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
+ {
+ int i, j = 0;
+ int plen = 0; /* length of skb->head fragment */
++ int ret;
+ struct page *page;
+ unsigned int offset;
+
+ BUG_ON(!from->head_frag && !hlen);
+
+ /* dont bother with small payloads */
+- if (len <= skb_tailroom(to)) {
+- skb_copy_bits(from, 0, skb_put(to, len), len);
+- return;
+- }
++ if (len <= skb_tailroom(to))
++ return skb_copy_bits(from, 0, skb_put(to, len), len);
+
+ if (hlen) {
+- skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
++ ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
++ if (unlikely(ret))
++ return ret;
+ len -= hlen;
+ } else {
+ plen = min_t(int, skb_headlen(from), len);
+@@ -2163,6 +2169,11 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
+ to->len += len + plen;
+ to->data_len += len + plen;
+
++ if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
++ skb_tx_error(from);
++ return -ENOMEM;
++ }
++
+ for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
+ if (!len)
+ break;
+@@ -2173,6 +2184,8 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
+ j++;
+ }
+ skb_shinfo(to)->nr_frags = j;
++
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(skb_zerocopy);
+
+diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
+index f072fe8..108120f 100644
+--- a/net/netfilter/nfnetlink_queue_core.c
++++ b/net/netfilter/nfnetlink_queue_core.c
+@@ -354,13 +354,16 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
+
+ skb = nfnetlink_alloc_skb(net, size, queue->peer_portid,
+ GFP_ATOMIC);
+- if (!skb)
++ if (!skb) {
++ skb_tx_error(entskb);
+ return NULL;
++ }
+
+ nlh = nlmsg_put(skb, 0, 0,
+ NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
+ sizeof(struct nfgenmsg), 0);
+ if (!nlh) {
++ skb_tx_error(entskb);
+ kfree_skb(skb);
+ return NULL;
+ }
+@@ -488,13 +491,15 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
+ nla->nla_type = NFQA_PAYLOAD;
+ nla->nla_len = nla_attr_size(data_len);
+
+- skb_zerocopy(skb, entskb, data_len, hlen);
++ if (skb_zerocopy(skb, entskb, data_len, hlen))
++ goto nla_put_failure;
+ }
+
+ nlh->nlmsg_len = skb->len;
+ return skb;
+
+ nla_put_failure:
++ skb_tx_error(entskb);
+ kfree_skb(skb);
+ net_err_ratelimited("nf_queue: error creating packet message\n");
+ return NULL;
+diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
+index 8601b32..270b77d 100644
+--- a/net/openvswitch/datapath.c
++++ b/net/openvswitch/datapath.c
+@@ -464,7 +464,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
+ }
+ nla->nla_len = nla_attr_size(skb->len);
+
+- skb_zerocopy(user_skb, skb, skb->len, hlen);
++ err = skb_zerocopy(user_skb, skb, skb->len, hlen);
++ if (err)
++ goto out;
+
+ /* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */
+ if (!(dp->user_features & OVS_DP_F_UNALIGNED)) {
+@@ -478,6 +480,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
+
+ err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);
+ out:
++ if (err)
++ skb_tx_error(skb);
+ kfree_skb(nskb);
+ return err;
+ }
+--
+cgit v0.10.1
+
diff --git a/kernel.spec b/kernel.spec
index b7cd5c09a..7c7842256 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -642,6 +642,9 @@ Patch25036: ppc64le_module_fix.patch
#rhbz 1046495
Patch25044: iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
+#CVE-2014-2568 rhbz 1079012 1079013
+Patch25049: core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch
+
# END OF PATCH DEFINITIONS
%endif
@@ -1289,6 +1292,9 @@ ApplyPatch ppc64le_module_fix.patch
#rhbz 1046495
ApplyPatch iwlwifi-dvm-take-mutex-when-sending-SYNC-BT-config-command.patch
+#CVE-2014-2568 rhbz 1079012 1079013
+ApplyPatch core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2068,6 +2074,9 @@ fi
# ||----w |
# || ||
%changelog
+* Fri Mar 28 2014 Josh Boyer <jwboyer@fedoraproject.org>
+- CVE-2014-2568 net: potential info leak when ubuf backed skbs are zero copied (rhbz 1079012 1079013)
+
* Fri Mar 28 2014 Josh Boyer <jwboyer@fedoraproject.org> - 3.14.0-0.rc8.git1.1
- Linux v3.14-rc8-12-g75c5a52
- Reenable debugging options.