Module Name:    src
Committed By:   ozaki-r
Date:           Mon Feb  3 07:40:24 UTC 2025

Modified Files:
        src/sys/altq: altq_rmclass.h

Log Message:
altq, cbq: fix TS_ADD_DELTA on ILP32

TS_ADD_DELTA adds a nanosecond value, delta, to a timespec value while
delta is int64_t and tv_nsec is long.  delta is guaranteed as positive
in ALTQ/CBQ.  However, the original code used delta after casting it
into long.  So it could be negative on ILP32 systems.  TS_ADD_DELTA
didn't assume that delta was negative and resulting tv_nsec could be
negative unexpectedly.

This issue was likely to occur when bandwidth borrowing was used where
the borrowing class had a absolutely small bandwidth (e.g., less than
10 Mbps) or a relatively small bandwidth (e.g., 10 Mbps when the parent
class had 200 Mbps).

KASSERT has been added to guarantee resulting tv_nsec is always not
negative.  Additionally, another KASSERT has been added to make it clear
that delta is assumed to be non-negative.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/altq/altq_rmclass.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/altq/altq_rmclass.h
diff -u src/sys/altq/altq_rmclass.h:1.13 src/sys/altq/altq_rmclass.h:1.14
--- src/sys/altq/altq_rmclass.h:1.13	Tue May 24 20:50:18 2022
+++ src/sys/altq/altq_rmclass.h	Mon Feb  3 07:40:24 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: altq_rmclass.h,v 1.13 2022/05/24 20:50:18 andvar Exp $	*/
+/*	$NetBSD: altq_rmclass.h,v 1.14 2025/02/03 07:40:24 ozaki-r Exp $	*/
 /*	$KAME: altq_rmclass.h,v 1.10 2003/08/20 23:30:23 itojun Exp $	*/
 
 /*
@@ -82,14 +82,14 @@ struct red;
 } while (0)
 
 #define	TS_ADD_DELTA(a, delta, res) do { \
-	register long xxns = (a)->tv_nsec + (long)(delta); \
-	\
-	(res)->tv_sec = (a)->tv_sec; \
-	while (xxns >= 1000000000) { \
-		++((res)->tv_sec); \
-		xxns -= 1000000000; \
+	KASSERT(delta >= 0); \
+	(res)->tv_sec = (a)->tv_sec + (delta) / 1000000000L; \
+	(res)->tv_nsec = (a)->tv_nsec + (long)((delta) % 1000000000L); \
+	if ((res)->tv_nsec >= 1000000000L) { \
+		(res)->tv_nsec -= 1000000000L; \
+		(res)->tv_sec++; \
 	} \
-	(res)->tv_nsec = xxns; \
+	KASSERT((res)->tv_nsec >= 0); \
 } while (0)
 
 #define	RM_TIMEOUT	2	/* 1 Clock tick. */

Reply via email to