Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 522bb2a2 authored by Pierre Peiffer's avatar Pierre Peiffer Committed by Linus Torvalds
Browse files

IPC/semaphores: move the rwmutex handling inside semctl_down



semctl_down is called with the rwmutex (the one which protects the list of
ipcs) taken in write mode.

This patch moves this rwmutex taken in write-mode inside semctl_down.

This has the advantages of reducing a little bit the window during which this
rwmutex is taken, clarifying sys_semctl, and finally of having a coherent
behaviour with [shm|msg]ctl_down

Signed-off-by: default avatarPierre Peiffer <pierre.peiffer@bull.net>
Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
Cc: Nadia Derbey <Nadia.Derbey@bull.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a0d092fc
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -875,6 +875,11 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
	}
}

/*
 * This function handles some semctl commands which require the rw_mutex
 * to be held in write mode.
 * NOTE: no locks must be held, the rw_mutex is taken inside this function.
 */
static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
		int cmd, int version, union semun arg)
{
@@ -887,9 +892,12 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
		if(copy_semid_from_user (&setbuf, arg.buf, version))
			return -EFAULT;
	}
	down_write(&sem_ids(ns).rw_mutex);
	sma = sem_lock_check_down(ns, semid);
	if (IS_ERR(sma))
		return PTR_ERR(sma);
	if (IS_ERR(sma)) {
		err = PTR_ERR(sma);
		goto out_up;
	}

	ipcp = &sma->sem_perm;

@@ -915,26 +923,22 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
	switch(cmd){
	case IPC_RMID:
		freeary(ns, ipcp);
		err = 0;
		break;
		goto out_up;
	case IPC_SET:
		ipcp->uid = setbuf.uid;
		ipcp->gid = setbuf.gid;
		ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
				| (setbuf.mode & S_IRWXUGO);
		sma->sem_ctime = get_seconds();
		sem_unlock(sma);
		err = 0;
		break;
	default:
		sem_unlock(sma);
		err = -EINVAL;
		break;
	}
	return err;

out_unlock:
	sem_unlock(sma);
out_up:
	up_write(&sem_ids(ns).rw_mutex);
	return err;
}

@@ -968,9 +972,7 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
		return err;
	case IPC_RMID:
	case IPC_SET:
		down_write(&sem_ids(ns).rw_mutex);
		err = semctl_down(ns,semid,semnum,cmd,version,arg);
		up_write(&sem_ids(ns).rw_mutex);
		return err;
	default:
		return -EINVAL;