DragonFlyBSD Kernel Audit
DF-0757 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/net/if_mib.c b/sys/net/if_mib.c
--- a/sys/net/if_mib.c
+++ b/sys/net/if_mib.c
@@ -130,16 +130,29 @@
 		ifmd.ifmd_snd_drops = ifp->if_snd.ifq_drops;
 #endif
 
+		/*
+		 * DF-0757: don't hold the global ifnet_lock across user
+		 * copyin/copyout (may fault/sleep).  ifmd is a complete local
+		 * snapshot; drop the lock for the user copies, then re-acquire
+		 * and revalidate before writing back.
+		 */
+		ifnet_unlock();
+
 		error = SYSCTL_OUT(req, &ifmd, sizeof ifmd);
 		if (error || !req->newptr) {
-			ifnet_unlock();
 			return error;
 		}
 
 		error = SYSCTL_IN(req, &ifmd, sizeof ifmd);
 		if (error) {
+			return error;
+		}
+
+		ifnet_lock();
+		if (name[0] <= 0 || name[0] > if_index ||
+		    ifindex2ifnet[name[0]] != ifp) {
 			ifnet_unlock();
-			return error;
+			return ENOENT;
 		}
 
 #define DONTCOPY(fld) ifmd.ifmd_data.ifi_##fld = ifp->if_data.ifi_##fld