aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/sem.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/sem.c')
-rw-r--r--ipc/sem.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 8c4f59b0204a..db9d241af133 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1282,6 +1282,12 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
1282 1282
1283 sem_lock(sma, NULL, -1); 1283 sem_lock(sma, NULL, -1);
1284 1284
1285 if (sma->sem_perm.deleted) {
1286 sem_unlock(sma, -1);
1287 rcu_read_unlock();
1288 return -EIDRM;
1289 }
1290
1285 curr = &sma->sem_base[semnum]; 1291 curr = &sma->sem_base[semnum];
1286 1292
1287 ipc_assert_locked_object(&sma->sem_perm); 1293 ipc_assert_locked_object(&sma->sem_perm);
@@ -1336,12 +1342,14 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
1336 int i; 1342 int i;
1337 1343
1338 sem_lock(sma, NULL, -1); 1344 sem_lock(sma, NULL, -1);
1345 if (sma->sem_perm.deleted) {
1346 err = -EIDRM;
1347 goto out_unlock;
1348 }
1339 if(nsems > SEMMSL_FAST) { 1349 if(nsems > SEMMSL_FAST) {
1340 if (!ipc_rcu_getref(sma)) { 1350 if (!ipc_rcu_getref(sma)) {
1341 sem_unlock(sma, -1);
1342 rcu_read_unlock();
1343 err = -EIDRM; 1351 err = -EIDRM;
1344 goto out_free; 1352 goto out_unlock;
1345 } 1353 }
1346 sem_unlock(sma, -1); 1354 sem_unlock(sma, -1);
1347 rcu_read_unlock(); 1355 rcu_read_unlock();
@@ -1354,10 +1362,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
1354 rcu_read_lock(); 1362 rcu_read_lock();
1355 sem_lock_and_putref(sma); 1363 sem_lock_and_putref(sma);
1356 if (sma->sem_perm.deleted) { 1364 if (sma->sem_perm.deleted) {
1357 sem_unlock(sma, -1);
1358 rcu_read_unlock();
1359 err = -EIDRM; 1365 err = -EIDRM;
1360 goto out_free; 1366 goto out_unlock;
1361 } 1367 }
1362 } 1368 }
1363 for (i = 0; i < sma->sem_nsems; i++) 1369 for (i = 0; i < sma->sem_nsems; i++)
@@ -1375,8 +1381,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
1375 struct sem_undo *un; 1381 struct sem_undo *un;
1376 1382
1377 if (!ipc_rcu_getref(sma)) { 1383 if (!ipc_rcu_getref(sma)) {
1378 rcu_read_unlock(); 1384 err = -EIDRM;
1379 return -EIDRM; 1385 goto out_rcu_wakeup;
1380 } 1386 }
1381 rcu_read_unlock(); 1387 rcu_read_unlock();
1382 1388
@@ -1404,10 +1410,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
1404 rcu_read_lock(); 1410 rcu_read_lock();
1405 sem_lock_and_putref(sma); 1411 sem_lock_and_putref(sma);
1406 if (sma->sem_perm.deleted) { 1412 if (sma->sem_perm.deleted) {
1407 sem_unlock(sma, -1);
1408 rcu_read_unlock();
1409 err = -EIDRM; 1413 err = -EIDRM;
1410 goto out_free; 1414 goto out_unlock;
1411 } 1415 }
1412 1416
1413 for (i = 0; i < nsems; i++) 1417 for (i = 0; i < nsems; i++)
@@ -1431,6 +1435,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
1431 goto out_rcu_wakeup; 1435 goto out_rcu_wakeup;
1432 1436
1433 sem_lock(sma, NULL, -1); 1437 sem_lock(sma, NULL, -1);
1438 if (sma->sem_perm.deleted) {
1439 err = -EIDRM;
1440 goto out_unlock;
1441 }
1434 curr = &sma->sem_base[semnum]; 1442 curr = &sma->sem_base[semnum];
1435 1443
1436 switch (cmd) { 1444 switch (cmd) {
@@ -1836,6 +1844,10 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1836 if (error) 1844 if (error)
1837 goto out_rcu_wakeup; 1845 goto out_rcu_wakeup;
1838 1846
1847 error = -EIDRM;
1848 locknum = sem_lock(sma, sops, nsops);
1849 if (sma->sem_perm.deleted)
1850 goto out_unlock_free;
1839 /* 1851 /*
1840 * semid identifiers are not unique - find_alloc_undo may have 1852 * semid identifiers are not unique - find_alloc_undo may have
1841 * allocated an undo structure, it was invalidated by an RMID 1853 * allocated an undo structure, it was invalidated by an RMID
@@ -1843,8 +1855,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1843 * This case can be detected checking un->semid. The existence of 1855 * This case can be detected checking un->semid. The existence of
1844 * "un" itself is guaranteed by rcu. 1856 * "un" itself is guaranteed by rcu.
1845 */ 1857 */
1846 error = -EIDRM;
1847 locknum = sem_lock(sma, sops, nsops);
1848 if (un && un->semid == -1) 1858 if (un && un->semid == -1)
1849 goto out_unlock_free; 1859 goto out_unlock_free;
1850 1860
@@ -2057,6 +2067,12 @@ void exit_sem(struct task_struct *tsk)
2057 } 2067 }
2058 2068
2059 sem_lock(sma, NULL, -1); 2069 sem_lock(sma, NULL, -1);
2070 /* exit_sem raced with IPC_RMID, nothing to do */
2071 if (sma->sem_perm.deleted) {
2072 sem_unlock(sma, -1);
2073 rcu_read_unlock();
2074 continue;
2075 }
2060 un = __lookup_undo(ulp, semid); 2076 un = __lookup_undo(ulp, semid);
2061 if (un == NULL) { 2077 if (un == NULL) {
2062 /* exit_sem raced with IPC_RMID+semget() that created 2078 /* exit_sem raced with IPC_RMID+semget() that created