DF-2784 / fix.diff
--- 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; |