DragonFlyBSD Kernel Audit
DF-0441 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/net/altq/altq_rmclass.c b/sys/net/altq/altq_rmclass.c
--- a/sys/net/altq/altq_rmclass.c
+++ b/sys/net/altq/altq_rmclass.c
@@ -234,6 +234,16 @@
 	cl->leaf_ = 1;
 	cl->ifdat_ = ifd;
 	cl->pri_ = pri;
+	/*
+	 * DF-0441: nsecPerByte == 0 would divide-by-zero below.  The value
+	 * arrives unchecked from a user-supplied struct pf_altq via
+	 * cbq_opts.ns_per_byte (altq_cbq.c:374).  pfctl computes it from
+	 * bandwidth ratios and never yields 0, but a malicious root can
+	 * issue DIOCADDALTQ directly with ns_per_byte = 0 and panic the
+	 * kernel.  Clamp to 1 ns/byte (the slowest non-zero rate) instead.
+	 */
+	if (nsecPerByte == 0)
+		nsecPerByte = 1;
 	cl->allotment_ = RM_NS_PER_SEC / nsecPerByte; /* Bytes per sec */
 	cl->depth_ = 0;
 	cl->qthresh_ = 0;
@@ -347,6 +357,13 @@
 	old_allotment = cl->allotment_;
 
 	crit_enter();
+	/*
+	 * DF-0441: same divide-by-zero guard as rmc_newclass(); see the
+	 * comment there.  rmc_modclass() takes the same unchecked user
+	 * nsecPerByte through cbq_modify_queue().
+	 */
+	if (nsecPerByte == 0)
+		nsecPerByte = 1;
 	cl->allotment_ = RM_NS_PER_SEC / nsecPerByte; /* Bytes per sec */
 	cl->qthresh_ = 0;
 	cl->ns_per_byte_ = nsecPerByte;