shithub: riscv

Download patch

ref: 575398eb9bc2c6f1bcfce7bf8fffbce73a96e8da
parent: 638b4a1ec113adebdd6a85d647574a46e0b7feab
author: cinap_lenrek <[email protected]>
date: Sun Apr 22 14:42:22 EDT 2018

devip: verify ifcid on routehint check, check Route.ref for free'd routes

v4lookup() and v6lookup() do not acquire the routelock, so it is
possible to hit routes that are on the freelist. to detect these,
we set ref to 0 and check for this case, avoiding overriding the ifc.

re-evaluate routes when the ifcid on the route hint doesnt match.

--- a/sys/src/9/ip/iproute.c
+++ b/sys/src/9/ip/iproute.c
@@ -22,6 +22,7 @@
 {
 	Route **l;
 
+	r->ref = 0;
 	r->left = nil;
 	r->right = nil;
 	if(r->type & Rv4)
@@ -541,8 +542,13 @@
 	Route *p, *q;
 	Ipifc *ifc;
 
-	if(rh != nil && rh->r != nil && rh->r->ifc != nil && rh->rgen == v4routegeneration)
-		return rh->r;
+	if(rh != nil
+	&& rh->rgen == v4routegeneration
+	&& (q = rh->r) != nil
+	&& (ifc = q->ifc) != nil
+	&& q->ifcid == ifc->ifcid
+	&& q->ref > 0)
+		return q;
 
 	la = nhgetl(a);
 	ls = nhgetl(s);
@@ -570,7 +576,10 @@
 		p = p->mid;
 	}
 
-	if(q != nil && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
+	if(q == nil || q->ref == 0)
+		return nil;
+
+	if(q->ifc == nil || q->ifcid != q->ifc->ifcid){
 		if(q->type & Rifc) {
 			hnputl(gate+IPv4off, q->v4.address);
 			memmove(gate, v4prefix, IPv4off);
@@ -602,13 +611,19 @@
 	Ipifc *ifc;
 	int h;
 
-	if(isv4(a) && isv4(s))
-		return v4lookup(f, a+IPv4off, s+IPv4off, rh);
-	if(isv4(s))
+	if(isv4(s)){
+		if(isv4(a))
+			return v4lookup(f, a+IPv4off, s+IPv4off, rh);
 		return nil;
+	}
 
-	if(rh != nil && rh->r != nil && rh->r->ifc != nil && rh->rgen == v6routegeneration)
-		return rh->r;
+	if(rh != nil
+	&& rh->rgen == v6routegeneration
+	&& (q = rh->r) != nil
+	&& (ifc = q->ifc) != nil
+	&& q->ifcid == ifc->ifcid
+	&& q->ref > 0)
+		return q;
 
 	for(h = 0; h < IPllen; h++){
 		la[h] = nhgetl(a+4*h);
@@ -668,7 +683,10 @@
 next:		;
 	}
 
-	if(q != nil && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
+	if(q == nil || q->ref == 0)
+		return nil;
+
+	if(q->ifc == nil || q->ifcid != q->ifc->ifcid){
 		if(q->type & Rifc) {
 			for(h = 0; h < IPllen; h++)
 				hnputl(gate+4*h, q->v6.address[h]);