Skip to contentSkip to conversation

fib6: Fix fn->leaf == NULL race when inserting new nodes in fib6 tree

PATCH In review Thomas Graf 2 participants 3 messages Jan 4, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 fib6: Fix fn->leaf == NULL race when inserting new nodes in fib6 tree

When inserting new nodes into a fib6 tree, the leaf pointer is first to NULL and later corrected when the key gets assigned. However, the tree is not locked for this period of time, therefore nodes with an invalid leaf pointer are accessible. Lookups that occur during this period of time expect a valid leaf pointer and thus crash.

This patch sets the leaf pointer to ip6_null_entry during this critical period of time.

net/ipv6/ip6_fib.c +18 -1
Index: net-2.6/net/ipv6/ip6_fib.c
===================================================================
@@ -150,9 +150,19 @@ static __inline__ struct fib6_node * nod
 {
 	struct fib6_node *fn;
 
-	if ((fn = kmem_cache_alloc(fib6_node_kmem, GFP_ATOMIC)) != NULL)
+	if ((fn = kmem_cache_alloc(fib6_node_kmem, GFP_ATOMIC)) != NULL) {
 		memset(fn, 0, sizeof(struct fib6_node));
 
+		/*
+		 * leaf is set to ip6_null_entry to provide a valid leaf
+		 * during the time period between inserting the node into
+		 * the tree and assigning the key. This is necessary because
+		 * the node is accessible during this period of time.
+		 */
+		fn->leaf = &ip6_null_entry;
+		fn->fn_flags |= RTN_TEMP_LEAF;
+	}
+
 	return fn;
 }
 
@@ -551,6 +561,7 @@ insert_above:
 		in->parent = pn;
 		in->leaf = fn->leaf;
 		atomic_inc(&in->leaf->rt6i_ref);
+		in->fn_flags &= ~RTN_TEMP_LEAF;
 
 		in->fn_sernum = sernum;
 
@@ -620,6 +631,12 @@ static int fib6_add_rt2node(struct fib6_
 
 	ins = &fn->leaf;
 
+	/* Avoid duplicate checks for temporary leafs */
+	if (fn->fn_flags & RTN_TEMP_LEAF) {
+		fn->fn_flags &= ~RTN_TEMP_LEAF;
+		goto out;
+	}
+
 	if (fn->fn_flags&RTN_TL_ROOT &&
 	    fn->leaf == &ip6_null_entry &&
 	    !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
include/net/ip6_fib.h +1 -0
Index: net-2.6/include/net/ip6_fib.h
===================================================================
@@ -135,6 +135,7 @@ struct rt6_statistics {
 #define RTN_TL_ROOT	0x0001
 #define RTN_ROOT	0x0002		/* tree root node		*/
 #define RTN_RTINFO	0x0004		/* node with valid routing info	*/
+#define RTN_TEMP_LEAF	0x0008		/* leaf is temporary		*/
 
 /*
  *	priority levels (or metrics)
#1 lore raw

* Thomas Graf <[email protected]> 2007-01-04 10:39

Quoted 9 lines

When inserting new nodes into a fib6 tree, the leaf pointer is first to NULL and later corrected when the key gets assigned. However, the tree is not locked for this period of time, therefore nodes with an invalid leaf pointer are accessible. Lookups that occur during this period of time expect a valid leaf pointer and thus crash.

This patch sets the leaf pointer to ip6_null_entry during this critical period of time.

Ignore this patch for now, the description is certainly inaccurate even though it seems to fix the issue.

maintainer
#2 lore raw

From: Thomas Graf <[email protected]>
Date: Thu, 4 Jan 2007 20:21:47 +0100

Quoted 8 lines

* Thomas Graf <[email protected]> 2007-01-04 10:39

Quoted 7 lines

When inserting new nodes into a fib6 tree, the leaf pointer is first to NULL and later corrected when the key gets assigned. However, the tree is not locked for this period of time, therefore nodes with an invalid leaf pointer are accessible. Lookups that occur during this period of time expect a valid leaf pointer and thus crash.

Quoted 5 lines
Quoted 2 lines

This patch sets the leaf pointer to ip6_null_entry during this critical period of time.

Ignore this patch for now, the description is certainly inaccurate even though it seems to fix the issue.

Ok, no problem.