|
@@ -188,7 +188,7 @@ void sem_exit_ns(struct ipc_namespace *ns)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-void __init sem_init (void)
|
|
|
+void __init sem_init(void)
|
|
|
{
|
|
|
sem_init_ns(&init_ipc_ns);
|
|
|
ipc_init_proc_interface("sysvipc/sem",
|
|
@@ -225,7 +225,7 @@ static void unmerge_queues(struct sem_array *sma)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * merge_queues - Merge single semop queues into global queue
|
|
|
+ * merge_queues - merge single semop queues into global queue
|
|
|
* @sma: semaphore array
|
|
|
*
|
|
|
* This function merges all per-semaphore queues into the global queue.
|
|
@@ -394,7 +394,7 @@ static inline struct sem_array *sem_obtain_lock(struct ipc_namespace *ns,
|
|
|
/* ipc_rmid() may have already freed the ID while sem_lock
|
|
|
* was spinning: verify that the structure is still valid
|
|
|
*/
|
|
|
- if (!ipcp->deleted)
|
|
|
+ if (ipc_valid_object(ipcp))
|
|
|
return container_of(ipcp, struct sem_array, sem_perm);
|
|
|
|
|
|
sem_unlock(sma, *locknum);
|
|
@@ -445,11 +445,11 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
|
|
|
* * call wake_up_process
|
|
|
* * set queue.status to the final value.
|
|
|
* - the previously blocked thread checks queue.status:
|
|
|
- * * if it's IN_WAKEUP, then it must wait until the value changes
|
|
|
- * * if it's not -EINTR, then the operation was completed by
|
|
|
- * update_queue. semtimedop can return queue.status without
|
|
|
- * performing any operation on the sem array.
|
|
|
- * * otherwise it must acquire the spinlock and check what's up.
|
|
|
+ * * if it's IN_WAKEUP, then it must wait until the value changes
|
|
|
+ * * if it's not -EINTR, then the operation was completed by
|
|
|
+ * update_queue. semtimedop can return queue.status without
|
|
|
+ * performing any operation on the sem array.
|
|
|
+ * * otherwise it must acquire the spinlock and check what's up.
|
|
|
*
|
|
|
* The two-stage algorithm is necessary to protect against the following
|
|
|
* races:
|
|
@@ -474,7 +474,6 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
|
|
|
*
|
|
|
* Called with sem_ids.rwsem held (as a writer)
|
|
|
*/
|
|
|
-
|
|
|
static int newary(struct ipc_namespace *ns, struct ipc_params *params)
|
|
|
{
|
|
|
int id;
|
|
@@ -491,12 +490,12 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
|
|
|
if (ns->used_sems + nsems > ns->sc_semmns)
|
|
|
return -ENOSPC;
|
|
|
|
|
|
- size = sizeof (*sma) + nsems * sizeof (struct sem);
|
|
|
+ size = sizeof(*sma) + nsems * sizeof(struct sem);
|
|
|
sma = ipc_rcu_alloc(size);
|
|
|
- if (!sma) {
|
|
|
+ if (!sma)
|
|
|
return -ENOMEM;
|
|
|
- }
|
|
|
- memset (sma, 0, size);
|
|
|
+
|
|
|
+ memset(sma, 0, size);
|
|
|
|
|
|
sma->sem_perm.mode = (semflg & S_IRWXUGO);
|
|
|
sma->sem_perm.key = key;
|
|
@@ -584,10 +583,11 @@ SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
|
|
|
return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params);
|
|
|
}
|
|
|
|
|
|
-/** perform_atomic_semop - Perform (if possible) a semaphore operation
|
|
|
+/**
|
|
|
+ * perform_atomic_semop - Perform (if possible) a semaphore operation
|
|
|
* @sma: semaphore array
|
|
|
* @sops: array with operations that should be checked
|
|
|
- * @nsems: number of sops
|
|
|
+ * @nsops: number of operations
|
|
|
* @un: undo array
|
|
|
* @pid: pid that did the change
|
|
|
*
|
|
@@ -595,19 +595,18 @@ SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
|
|
|
* Returns 1 if the operation is impossible, the caller must sleep.
|
|
|
* Negative values are error codes.
|
|
|
*/
|
|
|
-
|
|
|
static int perform_atomic_semop(struct sem_array *sma, struct sembuf *sops,
|
|
|
int nsops, struct sem_undo *un, int pid)
|
|
|
{
|
|
|
int result, sem_op;
|
|
|
struct sembuf *sop;
|
|
|
- struct sem * curr;
|
|
|
+ struct sem *curr;
|
|
|
|
|
|
for (sop = sops; sop < sops + nsops; sop++) {
|
|
|
curr = sma->sem_base + sop->sem_num;
|
|
|
sem_op = sop->sem_op;
|
|
|
result = curr->semval;
|
|
|
-
|
|
|
+
|
|
|
if (!sem_op && result)
|
|
|
goto would_block;
|
|
|
|
|
@@ -616,25 +615,24 @@ static int perform_atomic_semop(struct sem_array *sma, struct sembuf *sops,
|
|
|
goto would_block;
|
|
|
if (result > SEMVMX)
|
|
|
goto out_of_range;
|
|
|
+
|
|
|
if (sop->sem_flg & SEM_UNDO) {
|
|
|
int undo = un->semadj[sop->sem_num] - sem_op;
|
|
|
- /*
|
|
|
- * Exceeding the undo range is an error.
|
|
|
- */
|
|
|
+ /* Exceeding the undo range is an error. */
|
|
|
if (undo < (-SEMAEM - 1) || undo > SEMAEM)
|
|
|
goto out_of_range;
|
|
|
+ un->semadj[sop->sem_num] = undo;
|
|
|
}
|
|
|
+
|
|
|
curr->semval = result;
|
|
|
}
|
|
|
|
|
|
sop--;
|
|
|
while (sop >= sops) {
|
|
|
sma->sem_base[sop->sem_num].sempid = pid;
|
|
|
- if (sop->sem_flg & SEM_UNDO)
|
|
|
- un->semadj[sop->sem_num] -= sop->sem_op;
|
|
|
sop--;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
out_of_range:
|
|
@@ -650,7 +648,10 @@ would_block:
|
|
|
undo:
|
|
|
sop--;
|
|
|
while (sop >= sops) {
|
|
|
- sma->sem_base[sop->sem_num].semval -= sop->sem_op;
|
|
|
+ sem_op = sop->sem_op;
|
|
|
+ sma->sem_base[sop->sem_num].semval -= sem_op;
|
|
|
+ if (sop->sem_flg & SEM_UNDO)
|
|
|
+ un->semadj[sop->sem_num] += sem_op;
|
|
|
sop--;
|
|
|
}
|
|
|
|
|
@@ -680,7 +681,7 @@ static void wake_up_sem_queue_prepare(struct list_head *pt,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * wake_up_sem_queue_do(pt) - do the actual wake-up
|
|
|
+ * wake_up_sem_queue_do - do the actual wake-up
|
|
|
* @pt: list of tasks to be woken up
|
|
|
*
|
|
|
* Do the actual wake-up.
|
|
@@ -746,7 +747,7 @@ static int check_restart(struct sem_array *sma, struct sem_queue *q)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * wake_const_ops(sma, semnum, pt) - Wake up non-alter tasks
|
|
|
+ * wake_const_ops - wake up non-alter tasks
|
|
|
* @sma: semaphore array.
|
|
|
* @semnum: semaphore that was modified.
|
|
|
* @pt: list head for the tasks that must be woken up.
|
|
@@ -796,15 +797,14 @@ static int wake_const_ops(struct sem_array *sma, int semnum,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * do_smart_wakeup_zero(sma, sops, nsops, pt) - wakeup all wait for zero tasks
|
|
|
+ * do_smart_wakeup_zero - wakeup all wait for zero tasks
|
|
|
* @sma: semaphore array
|
|
|
* @sops: operations that were performed
|
|
|
* @nsops: number of operations
|
|
|
* @pt: list head of the tasks that must be woken up.
|
|
|
*
|
|
|
- * do_smart_wakeup_zero() checks all required queue for wait-for-zero
|
|
|
- * operations, based on the actual changes that were performed on the
|
|
|
- * semaphore array.
|
|
|
+ * Checks all required queue for wait-for-zero operations, based
|
|
|
+ * on the actual changes that were performed on the semaphore array.
|
|
|
* The function returns 1 if at least one operation was completed successfully.
|
|
|
*/
|
|
|
static int do_smart_wakeup_zero(struct sem_array *sma, struct sembuf *sops,
|
|
@@ -848,7 +848,7 @@ static int do_smart_wakeup_zero(struct sem_array *sma, struct sembuf *sops,
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * update_queue(sma, semnum): Look for tasks that can be completed.
|
|
|
+ * update_queue - look for tasks that can be completed.
|
|
|
* @sma: semaphore array.
|
|
|
* @semnum: semaphore that was modified.
|
|
|
* @pt: list head for the tasks that must be woken up.
|
|
@@ -918,7 +918,7 @@ again:
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * set_semotime(sma, sops) - set sem_otime
|
|
|
+ * set_semotime - set sem_otime
|
|
|
* @sma: semaphore array
|
|
|
* @sops: operations that modified the array, may be NULL
|
|
|
*
|
|
@@ -936,7 +936,7 @@ static void set_semotime(struct sem_array *sma, struct sembuf *sops)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue
|
|
|
+ * do_smart_update - optimized update_queue
|
|
|
* @sma: semaphore array
|
|
|
* @sops: operations that were performed
|
|
|
* @nsops: number of operations
|
|
@@ -998,21 +998,21 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
|
|
|
* The counts we return here are a rough approximation, but still
|
|
|
* warrant that semncnt+semzcnt>0 if the task is on the pending queue.
|
|
|
*/
|
|
|
-static int count_semncnt (struct sem_array * sma, ushort semnum)
|
|
|
+static int count_semncnt(struct sem_array *sma, ushort semnum)
|
|
|
{
|
|
|
int semncnt;
|
|
|
- struct sem_queue * q;
|
|
|
+ struct sem_queue *q;
|
|
|
|
|
|
semncnt = 0;
|
|
|
list_for_each_entry(q, &sma->sem_base[semnum].pending_alter, list) {
|
|
|
- struct sembuf * sops = q->sops;
|
|
|
+ struct sembuf *sops = q->sops;
|
|
|
BUG_ON(sops->sem_num != semnum);
|
|
|
if ((sops->sem_op < 0) && !(sops->sem_flg & IPC_NOWAIT))
|
|
|
semncnt++;
|
|
|
}
|
|
|
|
|
|
list_for_each_entry(q, &sma->pending_alter, list) {
|
|
|
- struct sembuf * sops = q->sops;
|
|
|
+ struct sembuf *sops = q->sops;
|
|
|
int nsops = q->nsops;
|
|
|
int i;
|
|
|
for (i = 0; i < nsops; i++)
|
|
@@ -1024,21 +1024,21 @@ static int count_semncnt (struct sem_array * sma, ushort semnum)
|
|
|
return semncnt;
|
|
|
}
|
|
|
|
|
|
-static int count_semzcnt (struct sem_array * sma, ushort semnum)
|
|
|
+static int count_semzcnt(struct sem_array *sma, ushort semnum)
|
|
|
{
|
|
|
int semzcnt;
|
|
|
- struct sem_queue * q;
|
|
|
+ struct sem_queue *q;
|
|
|
|
|
|
semzcnt = 0;
|
|
|
list_for_each_entry(q, &sma->sem_base[semnum].pending_const, list) {
|
|
|
- struct sembuf * sops = q->sops;
|
|
|
+ struct sembuf *sops = q->sops;
|
|
|
BUG_ON(sops->sem_num != semnum);
|
|
|
if ((sops->sem_op == 0) && !(sops->sem_flg & IPC_NOWAIT))
|
|
|
semzcnt++;
|
|
|
}
|
|
|
|
|
|
list_for_each_entry(q, &sma->pending_const, list) {
|
|
|
- struct sembuf * sops = q->sops;
|
|
|
+ struct sembuf *sops = q->sops;
|
|
|
int nsops = q->nsops;
|
|
|
int i;
|
|
|
for (i = 0; i < nsops; i++)
|
|
@@ -1108,7 +1108,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
|
|
|
|
|
|
static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in, int version)
|
|
|
{
|
|
|
- switch(version) {
|
|
|
+ switch (version) {
|
|
|
case IPC_64:
|
|
|
return copy_to_user(buf, in, sizeof(*in));
|
|
|
case IPC_OLD:
|
|
@@ -1151,7 +1151,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
|
|
|
int err;
|
|
|
struct sem_array *sma;
|
|
|
|
|
|
- switch(cmd) {
|
|
|
+ switch (cmd) {
|
|
|
case IPC_INFO:
|
|
|
case SEM_INFO:
|
|
|
{
|
|
@@ -1162,7 +1162,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
- memset(&seminfo,0,sizeof(seminfo));
|
|
|
+ memset(&seminfo, 0, sizeof(seminfo));
|
|
|
seminfo.semmni = ns->sc_semmni;
|
|
|
seminfo.semmns = ns->sc_semmns;
|
|
|
seminfo.semmsl = ns->sc_semmsl;
|
|
@@ -1183,7 +1183,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
|
|
|
up_read(&sem_ids(ns).rwsem);
|
|
|
if (copy_to_user(p, &seminfo, sizeof(struct seminfo)))
|
|
|
return -EFAULT;
|
|
|
- return (max_id < 0) ? 0: max_id;
|
|
|
+ return (max_id < 0) ? 0 : max_id;
|
|
|
}
|
|
|
case IPC_STAT:
|
|
|
case SEM_STAT:
|
|
@@ -1239,7 +1239,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
{
|
|
|
struct sem_undo *un;
|
|
|
struct sem_array *sma;
|
|
|
- struct sem* curr;
|
|
|
+ struct sem *curr;
|
|
|
int err;
|
|
|
struct list_head tasks;
|
|
|
int val;
|
|
@@ -1282,7 +1282,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
|
|
|
sem_lock(sma, NULL, -1);
|
|
|
|
|
|
- if (sma->sem_perm.deleted) {
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm)) {
|
|
|
sem_unlock(sma, -1);
|
|
|
rcu_read_unlock();
|
|
|
return -EIDRM;
|
|
@@ -1309,10 +1309,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
int cmd, void __user *p)
|
|
|
{
|
|
|
struct sem_array *sma;
|
|
|
- struct sem* curr;
|
|
|
+ struct sem *curr;
|
|
|
int err, nsems;
|
|
|
ushort fast_sem_io[SEMMSL_FAST];
|
|
|
- ushort* sem_io = fast_sem_io;
|
|
|
+ ushort *sem_io = fast_sem_io;
|
|
|
struct list_head tasks;
|
|
|
|
|
|
INIT_LIST_HEAD(&tasks);
|
|
@@ -1342,11 +1342,11 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
int i;
|
|
|
|
|
|
sem_lock(sma, NULL, -1);
|
|
|
- if (sma->sem_perm.deleted) {
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm)) {
|
|
|
err = -EIDRM;
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
- if(nsems > SEMMSL_FAST) {
|
|
|
+ if (nsems > SEMMSL_FAST) {
|
|
|
if (!ipc_rcu_getref(sma)) {
|
|
|
err = -EIDRM;
|
|
|
goto out_unlock;
|
|
@@ -1354,14 +1354,14 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
sem_unlock(sma, -1);
|
|
|
rcu_read_unlock();
|
|
|
sem_io = ipc_alloc(sizeof(ushort)*nsems);
|
|
|
- if(sem_io == NULL) {
|
|
|
+ if (sem_io == NULL) {
|
|
|
ipc_rcu_putref(sma, ipc_rcu_free);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
rcu_read_lock();
|
|
|
sem_lock_and_putref(sma);
|
|
|
- if (sma->sem_perm.deleted) {
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm)) {
|
|
|
err = -EIDRM;
|
|
|
goto out_unlock;
|
|
|
}
|
|
@@ -1371,7 +1371,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
sem_unlock(sma, -1);
|
|
|
rcu_read_unlock();
|
|
|
err = 0;
|
|
|
- if(copy_to_user(array, sem_io, nsems*sizeof(ushort)))
|
|
|
+ if (copy_to_user(array, sem_io, nsems*sizeof(ushort)))
|
|
|
err = -EFAULT;
|
|
|
goto out_free;
|
|
|
}
|
|
@@ -1386,15 +1386,15 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
}
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
- if(nsems > SEMMSL_FAST) {
|
|
|
+ if (nsems > SEMMSL_FAST) {
|
|
|
sem_io = ipc_alloc(sizeof(ushort)*nsems);
|
|
|
- if(sem_io == NULL) {
|
|
|
+ if (sem_io == NULL) {
|
|
|
ipc_rcu_putref(sma, ipc_rcu_free);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (copy_from_user (sem_io, p, nsems*sizeof(ushort))) {
|
|
|
+ if (copy_from_user(sem_io, p, nsems*sizeof(ushort))) {
|
|
|
ipc_rcu_putref(sma, ipc_rcu_free);
|
|
|
err = -EFAULT;
|
|
|
goto out_free;
|
|
@@ -1409,7 +1409,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
}
|
|
|
rcu_read_lock();
|
|
|
sem_lock_and_putref(sma);
|
|
|
- if (sma->sem_perm.deleted) {
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm)) {
|
|
|
err = -EIDRM;
|
|
|
goto out_unlock;
|
|
|
}
|
|
@@ -1435,7 +1435,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
goto out_rcu_wakeup;
|
|
|
|
|
|
sem_lock(sma, NULL, -1);
|
|
|
- if (sma->sem_perm.deleted) {
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm)) {
|
|
|
err = -EIDRM;
|
|
|
goto out_unlock;
|
|
|
}
|
|
@@ -1449,10 +1449,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
|
|
|
err = curr->sempid;
|
|
|
goto out_unlock;
|
|
|
case GETNCNT:
|
|
|
- err = count_semncnt(sma,semnum);
|
|
|
+ err = count_semncnt(sma, semnum);
|
|
|
goto out_unlock;
|
|
|
case GETZCNT:
|
|
|
- err = count_semzcnt(sma,semnum);
|
|
|
+ err = count_semzcnt(sma, semnum);
|
|
|
goto out_unlock;
|
|
|
}
|
|
|
|
|
@@ -1462,7 +1462,7 @@ out_rcu_wakeup:
|
|
|
rcu_read_unlock();
|
|
|
wake_up_sem_queue_do(&tasks);
|
|
|
out_free:
|
|
|
- if(sem_io != fast_sem_io)
|
|
|
+ if (sem_io != fast_sem_io)
|
|
|
ipc_free(sem_io, sizeof(ushort)*nsems);
|
|
|
return err;
|
|
|
}
|
|
@@ -1470,7 +1470,7 @@ out_free:
|
|
|
static inline unsigned long
|
|
|
copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
|
|
|
{
|
|
|
- switch(version) {
|
|
|
+ switch (version) {
|
|
|
case IPC_64:
|
|
|
if (copy_from_user(out, buf, sizeof(*out)))
|
|
|
return -EFAULT;
|
|
@@ -1479,7 +1479,7 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
|
|
|
{
|
|
|
struct semid_ds tbuf_old;
|
|
|
|
|
|
- if(copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
|
|
|
+ if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
|
|
|
return -EFAULT;
|
|
|
|
|
|
out->sem_perm.uid = tbuf_old.sem_perm.uid;
|
|
@@ -1506,7 +1506,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
|
|
|
struct semid64_ds semid64;
|
|
|
struct kern_ipc_perm *ipcp;
|
|
|
|
|
|
- if(cmd == IPC_SET) {
|
|
|
+ if (cmd == IPC_SET) {
|
|
|
if (copy_semid_from_user(&semid64, p, version))
|
|
|
return -EFAULT;
|
|
|
}
|
|
@@ -1566,7 +1566,7 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
|
|
|
version = ipc_parse_version(&cmd);
|
|
|
ns = current->nsproxy->ipc_ns;
|
|
|
|
|
|
- switch(cmd) {
|
|
|
+ switch (cmd) {
|
|
|
case IPC_INFO:
|
|
|
case SEM_INFO:
|
|
|
case IPC_STAT:
|
|
@@ -1634,7 +1634,7 @@ static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
|
|
|
{
|
|
|
struct sem_undo *un;
|
|
|
|
|
|
- assert_spin_locked(&ulp->lock);
|
|
|
+ assert_spin_locked(&ulp->lock);
|
|
|
|
|
|
un = __lookup_undo(ulp, semid);
|
|
|
if (un) {
|
|
@@ -1645,7 +1645,7 @@ static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * find_alloc_undo - Lookup (and if not present create) undo array
|
|
|
+ * find_alloc_undo - lookup (and if not present create) undo array
|
|
|
* @ns: namespace
|
|
|
* @semid: semaphore array id
|
|
|
*
|
|
@@ -1670,7 +1670,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
|
|
|
spin_lock(&ulp->lock);
|
|
|
un = lookup_undo(ulp, semid);
|
|
|
spin_unlock(&ulp->lock);
|
|
|
- if (likely(un!=NULL))
|
|
|
+ if (likely(un != NULL))
|
|
|
goto out;
|
|
|
|
|
|
/* no undo structure around - allocate one. */
|
|
@@ -1699,7 +1699,7 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
|
|
|
/* step 3: Acquire the lock on semaphore array */
|
|
|
rcu_read_lock();
|
|
|
sem_lock_and_putref(sma);
|
|
|
- if (sma->sem_perm.deleted) {
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm)) {
|
|
|
sem_unlock(sma, -1);
|
|
|
rcu_read_unlock();
|
|
|
kfree(new);
|
|
@@ -1735,7 +1735,7 @@ out:
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * get_queue_result - Retrieve the result code from sem_queue
|
|
|
+ * get_queue_result - retrieve the result code from sem_queue
|
|
|
* @q: Pointer to queue structure
|
|
|
*
|
|
|
* Retrieve the return code from the pending queue. If IN_WAKEUP is found in
|
|
@@ -1765,7 +1765,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
|
|
|
int error = -EINVAL;
|
|
|
struct sem_array *sma;
|
|
|
struct sembuf fast_sops[SEMOPM_FAST];
|
|
|
- struct sembuf* sops = fast_sops, *sop;
|
|
|
+ struct sembuf *sops = fast_sops, *sop;
|
|
|
struct sem_undo *un;
|
|
|
int undos = 0, alter = 0, max, locknum;
|
|
|
struct sem_queue queue;
|
|
@@ -1779,13 +1779,13 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
|
|
|
return -EINVAL;
|
|
|
if (nsops > ns->sc_semopm)
|
|
|
return -E2BIG;
|
|
|
- if(nsops > SEMOPM_FAST) {
|
|
|
- sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
|
|
|
- if(sops==NULL)
|
|
|
+ if (nsops > SEMOPM_FAST) {
|
|
|
+ sops = kmalloc(sizeof(*sops)*nsops, GFP_KERNEL);
|
|
|
+ if (sops == NULL)
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
- if (copy_from_user (sops, tsops, nsops * sizeof(*tsops))) {
|
|
|
- error=-EFAULT;
|
|
|
+ if (copy_from_user(sops, tsops, nsops * sizeof(*tsops))) {
|
|
|
+ error = -EFAULT;
|
|
|
goto out_free;
|
|
|
}
|
|
|
if (timeout) {
|
|
@@ -1846,7 +1846,15 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
|
|
|
|
|
|
error = -EIDRM;
|
|
|
locknum = sem_lock(sma, sops, nsops);
|
|
|
- if (sma->sem_perm.deleted)
|
|
|
+ /*
|
|
|
+ * We eventually might perform the following check in a lockless
|
|
|
+ * fashion, considering ipc_valid_object() locking constraints.
|
|
|
+ * If nsops == 1 and there is no contention for sem_perm.lock, then
|
|
|
+ * only a per-semaphore lock is held and it's OK to proceed with the
|
|
|
+ * check below. More details on the fine grained locking scheme
|
|
|
+ * entangled here and why it's RMID race safe on comments at sem_lock()
|
|
|
+ */
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm))
|
|
|
goto out_unlock_free;
|
|
|
/*
|
|
|
* semid identifiers are not unique - find_alloc_undo may have
|
|
@@ -1959,10 +1967,8 @@ sleep_again:
|
|
|
* If queue.status != -EINTR we are woken up by another process.
|
|
|
* Leave without unlink_queue(), but with sem_unlock().
|
|
|
*/
|
|
|
-
|
|
|
- if (error != -EINTR) {
|
|
|
+ if (error != -EINTR)
|
|
|
goto out_unlock_free;
|
|
|
- }
|
|
|
|
|
|
/*
|
|
|
* If an interrupt occurred we have to clean up the queue
|
|
@@ -1984,7 +1990,7 @@ out_rcu_wakeup:
|
|
|
rcu_read_unlock();
|
|
|
wake_up_sem_queue_do(&tasks);
|
|
|
out_free:
|
|
|
- if(sops != fast_sops)
|
|
|
+ if (sops != fast_sops)
|
|
|
kfree(sops);
|
|
|
return error;
|
|
|
}
|
|
@@ -2068,7 +2074,7 @@ void exit_sem(struct task_struct *tsk)
|
|
|
|
|
|
sem_lock(sma, NULL, -1);
|
|
|
/* exit_sem raced with IPC_RMID, nothing to do */
|
|
|
- if (sma->sem_perm.deleted) {
|
|
|
+ if (!ipc_valid_object(&sma->sem_perm)) {
|
|
|
sem_unlock(sma, -1);
|
|
|
rcu_read_unlock();
|
|
|
continue;
|
|
@@ -2093,7 +2099,7 @@ void exit_sem(struct task_struct *tsk)
|
|
|
|
|
|
/* perform adjustments registered in un */
|
|
|
for (i = 0; i < sma->sem_nsems; i++) {
|
|
|
- struct sem * semaphore = &sma->sem_base[i];
|
|
|
+ struct sem *semaphore = &sma->sem_base[i];
|
|
|
if (un->semadj[i]) {
|
|
|
semaphore->semval += un->semadj[i];
|
|
|
/*
|
|
@@ -2107,7 +2113,7 @@ void exit_sem(struct task_struct *tsk)
|
|
|
* Linux caps the semaphore value, both at 0
|
|
|
* and at SEMVMX.
|
|
|
*
|
|
|
- * Manfred <manfred@colorfullife.com>
|
|
|
+ * Manfred <manfred@colorfullife.com>
|
|
|
*/
|
|
|
if (semaphore->semval < 0)
|
|
|
semaphore->semval = 0;
|