add CVE-2017-12193 fix

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
diff --git a/queue/assoc_array-Fix-a-buggy-node-splitting-case.patch b/queue/assoc_array-Fix-a-buggy-node-splitting-case.patch
new file mode 100644
index 0000000..3b7fc0e
--- /dev/null
+++ b/queue/assoc_array-Fix-a-buggy-node-splitting-case.patch
@@ -0,0 +1,121 @@
+From ea6789980fdaa610d7eb63602c746bf6ec70cd2b Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Wed, 11 Oct 2017 23:32:27 +0100
+Subject: [PATCH] assoc_array: Fix a buggy node-splitting case
+
+commit ea6789980fdaa610d7eb63602c746bf6ec70cd2b upstream.
+
+This fixes CVE-2017-12193.
+
+Fix a case in the assoc_array implementation in which a new leaf is
+added that needs to go into a node that happens to be full, where the
+existing leaves in that node cluster together at that level to the
+exclusion of new leaf.
+
+What needs to happen is that the existing leaves get moved out to a new
+node, N1, at level + 1 and the existing node needs replacing with one,
+N0, that has pointers to the new leaf and to N1.
+
+The code that tries to do this gets this wrong in two ways:
+
+ (1) The pointer that should've pointed from N0 to N1 is set to point
+     recursively to N0 instead.
+
+ (2) The backpointer from N0 needs to be set correctly in the case N0 is
+     either the root node or reached through a shortcut.
+
+Fix this by removing this path and using the split_node path instead,
+which achieves the same end, but in a more general way (thanks to Eric
+Biggers for spotting the redundancy).
+
+The problem manifests itself as:
+
+  BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
+  IP: assoc_array_apply_edit+0x59/0xe5
+
+Fixes: 3cb989501c26 ("Add a generic associative array implementation.")
+Reported-and-tested-by: WU Fan <u3536072@connect.hku.hk>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Cc: stable@vger.kernel.org [v3.13-rc1+]
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+
+diff --git a/lib/assoc_array.c b/lib/assoc_array.c
+index 155c55d8db5f..4e53be8bc590 100644
+--- a/lib/assoc_array.c
++++ b/lib/assoc_array.c
+@@ -598,21 +598,31 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
+ 		if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0)
+ 			goto all_leaves_cluster_together;
+ 
+-		/* Otherwise we can just insert a new node ahead of the old
+-		 * one.
++		/* Otherwise all the old leaves cluster in the same slot, but
++		 * the new leaf wants to go into a different slot - so we
++		 * create a new node (n0) to hold the new leaf and a pointer to
++		 * a new node (n1) holding all the old leaves.
++		 *
++		 * This can be done by falling through to the node splitting
++		 * path.
+ 		 */
+-		goto present_leaves_cluster_but_not_new_leaf;
++		pr_devel("present leaves cluster but not new leaf\n");
+ 	}
+ 
+ split_node:
+ 	pr_devel("split node\n");
+ 
+-	/* We need to split the current node; we know that the node doesn't
+-	 * simply contain a full set of leaves that cluster together (it
+-	 * contains meta pointers and/or non-clustering leaves).
++	/* We need to split the current node.  The node must contain anything
++	 * from a single leaf (in the one leaf case, this leaf will cluster
++	 * with the new leaf) and the rest meta-pointers, to all leaves, some
++	 * of which may cluster.
++	 *
++	 * It won't contain the case in which all the current leaves plus the
++	 * new leaves want to cluster in the same slot.
+ 	 *
+ 	 * We need to expel at least two leaves out of a set consisting of the
+-	 * leaves in the node and the new leaf.
++	 * leaves in the node and the new leaf.  The current meta pointers can
++	 * just be copied as they shouldn't cluster with any of the leaves.
+ 	 *
+ 	 * We need a new node (n0) to replace the current one and a new node to
+ 	 * take the expelled nodes (n1).
+@@ -717,33 +727,6 @@ found_slot_for_multiple_occupancy:
+ 	pr_devel("<--%s() = ok [split node]\n", __func__);
+ 	return true;
+ 
+-present_leaves_cluster_but_not_new_leaf:
+-	/* All the old leaves cluster in the same slot, but the new leaf wants
+-	 * to go into a different slot, so we create a new node to hold the new
+-	 * leaf and a pointer to a new node holding all the old leaves.
+-	 */
+-	pr_devel("present leaves cluster but not new leaf\n");
+-
+-	new_n0->back_pointer = node->back_pointer;
+-	new_n0->parent_slot = node->parent_slot;
+-	new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch;
+-	new_n1->back_pointer = assoc_array_node_to_ptr(new_n0);
+-	new_n1->parent_slot = edit->segment_cache[0];
+-	new_n1->nr_leaves_on_branch = node->nr_leaves_on_branch;
+-	edit->adjust_count_on = new_n0;
+-
+-	for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++)
+-		new_n1->slots[i] = node->slots[i];
+-
+-	new_n0->slots[edit->segment_cache[0]] = assoc_array_node_to_ptr(new_n0);
+-	edit->leaf_p = &new_n0->slots[edit->segment_cache[ASSOC_ARRAY_FAN_OUT]];
+-
+-	edit->set[0].ptr = &assoc_array_ptr_to_node(node->back_pointer)->slots[node->parent_slot];
+-	edit->set[0].to = assoc_array_node_to_ptr(new_n0);
+-	edit->excised_meta[0] = assoc_array_node_to_ptr(node);
+-	pr_devel("<--%s() = ok [insert node before]\n", __func__);
+-	return true;
+-
+ all_leaves_cluster_together:
+ 	/* All the leaves, new and old, want to cluster together in this node
+ 	 * in the same slot, so we have to replace this node with a shortcut to
+-- 
+2.15.0
+
diff --git a/queue/series b/queue/series
new file mode 100644
index 0000000..9aa0e96
--- /dev/null
+++ b/queue/series
@@ -0,0 +1,2 @@
+# v4.14-rc7~7
+assoc_array-Fix-a-buggy-node-splitting-case.patch