git: 9front

Download patch

ref: 6c7e731d075b3fe9aa250ac457a25bc923ee426a
parent: b2fc8d4a337e2f82eb78ac8fe53c57648d200793
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 10 10:27:08 EDT 2021

devip: properly rlock() the routelock for v4lookup() and v6lookup()

i'm not confident about mutating the route tree
pointers and have concurrent readers walking the
pointer chains.

given that most route lookups are bypassed now
for non-routing case and we are not building a
high performance router here, lets play it safe.

--- a/sys/src/9/ip/iproute.c
+++ b/sys/src/9/ip/iproute.c
@@ -47,14 +47,10 @@
 		l = &v6freelist;
 	}
 
-	r = *l;
-	if(r != nil){
+	if((r = *l) != nil)
 		*l = r->mid;
-	} else {
-		r = malloc(n);
-		if(r == nil)
-			panic("out of routing nodes");
-	}
+	else
+		r = smalloc(n);
 	memset(r, 0, n);
 	r->type = type;
 	r->ifc = nil;
@@ -388,7 +384,7 @@
 static void
 routeadd(Fs *f, Route *r)
 {
-	Route **h, **e, *p;
+	Route **h, **e, *p, *q;
 
 	if(r->type & Rv4){
 		h = &f->v4root[V4H(r->v4.address)];
@@ -414,8 +410,9 @@
 		addnode(f, h, p);
 		while((p = f->queue) != nil) {
 			f->queue = p->mid;
-			walkadd(f, h, p->left);
+			q = p->left;
 			freeroute(p);
+			walkadd(f, h, q);
 		}
 	}
 
@@ -428,7 +425,7 @@
 static void
 routerem(Fs *f, Route *r)
 {
-	Route **h, **e, **l, *p;
+	Route **h, **e, **l, *p, *q;
 
 	if(r->type & Rv4){
 		h = &f->v4root[V4H(r->v4.address)];
@@ -452,8 +449,9 @@
 
 		while((p = f->queue) != nil) {
 			f->queue = p->mid;
-			walkadd(f, h, p->left);
+			q = p->left;
 			freeroute(p);
+			walkadd(f, h, q);
 		}
 	}
 
@@ -605,9 +603,11 @@
 	&& q->ref > 0)
 		return q;
 
+	q = nil;
 	la = nhgetl(a);
 	ls = nhgetl(s);
-	q = nil;
+
+	rlock(&routelock);
 	for(p = f->v4root[V4H(la)]; p != nil;){
 		if(la < p->v4.address){
 			p = p->left;
@@ -630,15 +630,15 @@
 		q = p;
 		p = p->mid;
 	}
-
-	if(q == nil || q->ref == 0 || routefindipifc(q, f) == nil)
-		return nil;
-
-	if(rh != nil){
-		rh->r = q;
-		rh->rgen = v4routegeneration;
+	if(q != nil){
+		if(routefindipifc(q, f) == nil)
+			q = nil;
+		else if(rh != nil){
+			rh->r = q;
+			rh->rgen = v4routegeneration;
+		}
 	}
-
+	runlock(&routelock);
 	return q;
 }
 
@@ -665,12 +665,13 @@
 	&& q->ref > 0)
 		return q;
 
+	q = nil;
 	for(h = 0; h < IPllen; h++){
 		la[h] = nhgetl(a+4*h);
 		ls[h] = nhgetl(s+4*h);
 	}
 
-	q = nil;
+	rlock(&routelock);
 	for(p = f->v6root[V6H(la)]; p != nil;){
 		for(h = 0; h < IPllen; h++){
 			x = la[h];
@@ -722,15 +723,15 @@
 		p = p->mid;
 next:		;
 	}
-
-	if(q == nil || q->ref == 0 || routefindipifc(q, f) == nil)
-		return nil;
-
-	if(rh != nil){
-		rh->r = q;
-		rh->rgen = v6routegeneration;
+	if(q != nil){
+		if(routefindipifc(q, f) == nil)
+			q = nil;
+		else if(rh != nil){
+			rh->r = q;
+			rh->rgen = v6routegeneration;
+		}
 	}
-	
+	runlock(&routelock);
 	return q;
 }
 
--