Page MenuHomeFreeBSD

D59347.id185729.diff
No OneTemporary

D59347.id185729.diff

diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -542,6 +542,7 @@
static int
semvalid(int semid, struct prison *rpr, struct semid_kernel *semakptr)
{
+ mtx_assert(&sema_mtx[IPCID_TO_IX(semid)], MA_OWNED);
return ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
semakptr->u.sem_perm.seq != IPCID_TO_SEQ(semid) ||
@@ -1111,10 +1112,9 @@
struct sem_undo *suptr;
struct mtx *sema_mtxp;
sbintime_t sbt, precision;
- size_t i, j, k;
+ size_t i, j, k, perms;
int error;
- int do_wakeup, do_undos;
- unsigned short seq;
+ bool do_wakeup, do_undos;
#ifdef SEM_DEBUG
sops = NULL;
@@ -1182,44 +1182,22 @@
semakptr = &sema[semid];
sema_mtxp = &sema_mtx[semid];
mtx_lock(sema_mtxp);
- if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0) {
- error = EINVAL;
- goto done2;
- }
- seq = semakptr->u.sem_perm.seq;
- if (seq != IPCID_TO_SEQ(usemid)) {
+ if (semvalid(semid, rpr, semakptr) != 0) {
error = EINVAL;
goto done2;
}
- if ((error = sem_prison_cansee(rpr, semakptr)) != 0)
- goto done2;
+
/*
* Initial pass through sops to see what permissions are needed.
- * Also perform any checks that don't need repeating on each
- * attempt to satisfy the request vector.
*/
- j = 0; /* permission needed */
- do_undos = 0;
+ perms = 0;
+ do_undos = false;
for (i = 0; i < nsops; i++) {
sopptr = &sops[i];
- if (sopptr->sem_num >= semakptr->u.sem_nsems) {
- error = EFBIG;
- goto done2;
- }
if (sopptr->sem_flg & SEM_UNDO && sopptr->sem_op != 0)
- do_undos = 1;
- j |= (sopptr->sem_op == 0) ? SEM_R : SEM_A;
- }
-
- if ((error = ipcperm(td, &semakptr->u.sem_perm, j))) {
- DPRINTF(("error = %d from ipaccess\n", error));
- goto done2;
+ do_undos = true;
+ perms |= (sopptr->sem_op == 0) ? SEM_R : SEM_A;
}
-#ifdef MAC
- error = mac_sysvsem_check_semop(td->td_ucred, semakptr, j);
- if (error != 0)
- goto done2;
-#endif
/*
* Loop trying to satisfy the vector of requests.
@@ -1231,11 +1209,25 @@
* of requests is atomic (never partially satisfied).
*/
for (;;) {
- do_wakeup = 0;
+ if ((error = ipcperm(td, &semakptr->u.sem_perm, perms))) {
+ DPRINTF(("error = %d from ipaccess\n", error));
+ goto done2;
+ }
+#ifdef MAC
+ error = mac_sysvsem_check_semop(td->td_ucred, semakptr, perms);
+ if (error != 0)
+ goto done2;
+#endif
+
+ do_wakeup = false;
error = 0; /* error return if necessary */
for (i = 0; i < nsops; i++) {
sopptr = &sops[i];
+ if (sopptr->sem_num >= semakptr->u.sem_nsems) {
+ error = EFBIG;
+ goto done2;
+ }
semptr = &semakptr->u.__sem_base[sopptr->sem_num];
DPRINTF((
@@ -1254,7 +1246,7 @@
semptr->semval += sopptr->sem_op;
if (semptr->semval == 0 &&
semptr->semzcnt > 0)
- do_wakeup = 1;
+ do_wakeup = true;
}
} else if (sopptr->sem_op == 0) {
if (semptr->semval != 0) {
@@ -1267,7 +1259,7 @@
break;
} else {
if (semptr->semncnt > 0)
- do_wakeup = 1;
+ do_wakeup = true;
semptr->semval += sopptr->sem_op;
}
}
@@ -1311,11 +1303,21 @@
/* return code is checked below, after sem[nz]cnt-- */
/*
- * Make sure that the semaphore still exists
+ * Make sure that the semaphore still exists.
+ */
+ if (semvalid(semid, rpr, semakptr) != 0) {
+ error = EIDRM;
+ goto done2;
+ }
+
+ /*
+ * Unfortunately, the check above isn't sufficient due to the
+ * possibility of wraparound in the sequence number. Do some
+ * more validation to try and catch this. Ideally we could
+ * maintain a wider sequence number, but this would change the
+ * KBI and some userspace applications depend on it.
*/
- seq = semakptr->u.sem_perm.seq;
- if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 ||
- seq != IPCID_TO_SEQ(usemid)) {
+ if (sopptr->sem_num >= semakptr->u.sem_nsems) {
error = EIDRM;
goto done2;
}
@@ -1368,8 +1370,8 @@
adjval = sops[i].sem_op;
if (adjval == 0)
continue;
- error = semundo_adjust(td, &suptr, semid, seq,
- sops[i].sem_num, -adjval);
+ error = semundo_adjust(td, &suptr, semid,
+ semakptr->u.sem_perm.seq, sops[i].sem_num, -adjval);
if (error == 0)
continue;
@@ -1389,8 +1391,9 @@
adjval = sops[k].sem_op;
if (adjval == 0)
continue;
- if (semundo_adjust(td, &suptr, semid, seq,
- sops[k].sem_num, adjval) != 0)
+ if (semundo_adjust(td, &suptr, semid,
+ semakptr->u.sem_perm.seq, sops[k].sem_num,
+ adjval) != 0)
panic("semop - can't undo undos");
}

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 3, 2:52 AM (15 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38257269
Default Alt Text
D59347.id185729.diff (4 KB)

Event Timeline