DragonFlyBSD Kernel Audit
DF-2784 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -238,10 +238,18 @@
 	for (i = 0; i < suptr->un_cnt; i++, sunptr++) {
 		if (sunptr->un_id != semid || sunptr->un_num != semnum)
 			continue;
-		if (adjval == 0)
+		if (adjval == 0) {
 			sunptr->un_adjval = 0;
-		else
-			sunptr->un_adjval += adjval;
+		} else {
+			int nadj = (int)sunptr->un_adjval + adjval;
+
+			/* enforce SEMAEM: un_adjval must not overflow */
+			if (nadj > seminfo.semaem || nadj < -seminfo.semaem) {
+				error = ERANGE;
+				goto done;
+			}
+			sunptr->un_adjval = nadj;
+		}
 		if (sunptr->un_adjval == 0) {
 			suptr->un_cnt--;
 			if (i < suptr->un_cnt)
@@ -253,7 +261,9 @@
 	/* Didn't find the right entry - create it */
 	if (adjval == 0)
 		goto done;
-	if (suptr->un_cnt != seminfo.semume) {
+	if (adjval > seminfo.semaem || adjval < -seminfo.semaem) {
+		error = ERANGE;
+	} else if (suptr->un_cnt != seminfo.semume) {
 		sunptr = &suptr->un_ent[suptr->un_cnt];
 		suptr->un_cnt++;
 		sunptr->un_adjval = adjval;