Skip to content

Commit

Permalink
ipc: integrate ipc_checkid() into ipc_lock()
Browse files Browse the repository at this point in the history
This patch introduces a new ipc_lock_check() routine interface:
   . each time ipc_checkid() is called, this is done after calling ipc_lock().
     ipc_checkid() is now called from inside ipc_lock_check().

[[email protected]: build fix]
[[email protected]: fix RCU locking]
Signed-off-by: Nadia Derbey <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Nadia Derbey authored and Linus Torvalds committed Oct 19, 2007
1 parent 637c366 commit 023a535
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 136 deletions.
62 changes: 30 additions & 32 deletions ipc/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ static struct ipc_ids init_msg_ids;

#define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS]))

#define msg_lock(ns, id) ((struct msg_queue*)ipc_lock(&msg_ids(ns), id))
#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm)
#define msg_checkid(ns, msq, msgid) \
ipc_checkid(&msg_ids(ns), &msq->q_perm, msgid)
#define msg_buildid(ns, id, seq) \
ipc_buildid(&msg_ids(ns), id, seq)

Expand Down Expand Up @@ -139,6 +136,17 @@ void __init msg_init(void)
IPC_MSG_IDS, sysvipc_msg_proc_show);
}

static inline struct msg_queue *msg_lock(struct ipc_namespace *ns, int id)
{
return (struct msg_queue *) ipc_lock(&msg_ids(ns), id);
}

static inline struct msg_queue *msg_lock_check(struct ipc_namespace *ns,
int id)
{
return (struct msg_queue *) ipc_lock_check(&msg_ids(ns), id);
}

static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
{
ipc_rmid(&msg_ids(ns), &s->q_perm);
Expand Down Expand Up @@ -445,18 +453,15 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
if (!buf)
return -EFAULT;

memset(&tbuf, 0, sizeof(tbuf));

msq = msg_lock(ns, msqid);
if (msq == NULL)
return -EINVAL;

if (cmd == MSG_STAT) {
msq = msg_lock(ns, msqid);
if (IS_ERR(msq))
return PTR_ERR(msq);
success_return = msq->q_perm.id;
} else {
err = -EIDRM;
if (msg_checkid(ns, msq, msqid))
goto out_unlock;
msq = msg_lock_check(ns, msqid);
if (IS_ERR(msq))
return PTR_ERR(msq);
success_return = 0;
}
err = -EACCES;
Expand All @@ -467,6 +472,8 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
if (err)
goto out_unlock;

memset(&tbuf, 0, sizeof(tbuf));

kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
tbuf.msg_stime = msq->q_stime;
tbuf.msg_rtime = msq->q_rtime;
Expand Down Expand Up @@ -494,14 +501,12 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
}

mutex_lock(&msg_ids(ns).mutex);
msq = msg_lock(ns, msqid);
err = -EINVAL;
if (msq == NULL)
msq = msg_lock_check(ns, msqid);
if (IS_ERR(msq)) {
err = PTR_ERR(msq);
goto out_up;
}

err = -EIDRM;
if (msg_checkid(ns, msq, msqid))
goto out_unlock_up;
ipcp = &msq->q_perm;

err = audit_ipc_obj(ipcp);
Expand Down Expand Up @@ -644,14 +649,11 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
msg->m_type = mtype;
msg->m_ts = msgsz;

msq = msg_lock(ns, msqid);
err = -EINVAL;
if (msq == NULL)
msq = msg_lock_check(ns, msqid);
if (IS_ERR(msq)) {
err = PTR_ERR(msq);
goto out_free;

err= -EIDRM;
if (msg_checkid(ns, msq, msqid))
goto out_unlock_free;
}

for (;;) {
struct msg_sender s;
Expand Down Expand Up @@ -758,13 +760,9 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
mode = convert_mode(&msgtyp, msgflg);
ns = current->nsproxy->ipc_ns;

msq = msg_lock(ns, msqid);
if (msq == NULL)
return -EINVAL;

msg = ERR_PTR(-EIDRM);
if (msg_checkid(ns, msq, msqid))
goto out_unlock;
msq = msg_lock_check(ns, msqid);
if (IS_ERR(msq))
return PTR_ERR(msq);

for (;;) {
struct msg_receiver msr_d;
Expand Down
70 changes: 33 additions & 37 deletions ipc/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@

#define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS]))

#define sem_lock(ns, id) ((struct sem_array*)ipc_lock(&sem_ids(ns), id))
#define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm)
#define sem_checkid(ns, sma, semid) \
ipc_checkid(&sem_ids(ns),&sma->sem_perm,semid)
Expand Down Expand Up @@ -175,6 +174,17 @@ void __init sem_init (void)
IPC_SEM_IDS, sysvipc_sem_proc_show);
}

static inline struct sem_array *sem_lock(struct ipc_namespace *ns, int id)
{
return (struct sem_array *) ipc_lock(&sem_ids(ns), id);
}

static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns,
int id)
{
return (struct sem_array *) ipc_lock_check(&sem_ids(ns), id);
}

static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
{
ipc_rmid(&sem_ids(ns), &s->sem_perm);
Expand Down Expand Up @@ -599,11 +609,9 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
struct semid64_ds tbuf;
int id;

memset(&tbuf,0,sizeof(tbuf));

sma = sem_lock(ns, semid);
if(sma == NULL)
return -EINVAL;
if (IS_ERR(sma))
return PTR_ERR(sma);

err = -EACCES;
if (ipcperms (&sma->sem_perm, S_IRUGO))
Expand All @@ -615,6 +623,8 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,

id = sma->sem_perm.id;

memset(&tbuf, 0, sizeof(tbuf));

kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
tbuf.sem_otime = sma->sem_otime;
tbuf.sem_ctime = sma->sem_ctime;
Expand Down Expand Up @@ -643,16 +653,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
ushort* sem_io = fast_sem_io;
int nsems;

sma = sem_lock(ns, semid);
if(sma==NULL)
return -EINVAL;
sma = sem_lock_check(ns, semid);
if (IS_ERR(sma))
return PTR_ERR(sma);

nsems = sma->sem_nsems;

err=-EIDRM;
if (sem_checkid(ns,sma,semid))
goto out_unlock;

err = -EACCES;
if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
goto out_unlock;
Expand Down Expand Up @@ -864,14 +870,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
if(copy_semid_from_user (&setbuf, arg.buf, version))
return -EFAULT;
}
sma = sem_lock(ns, semid);
if(sma==NULL)
return -EINVAL;
sma = sem_lock_check(ns, semid);
if (IS_ERR(sma))
return PTR_ERR(sma);

if (sem_checkid(ns,sma,semid)) {
err=-EIDRM;
goto out_unlock;
}
ipcp = &sma->sem_perm;

err = audit_ipc_obj(ipcp);
Expand Down Expand Up @@ -1055,15 +1057,10 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
goto out;

/* no undo structure around - allocate one. */
sma = sem_lock(ns, semid);
un = ERR_PTR(-EINVAL);
if(sma==NULL)
goto out;
un = ERR_PTR(-EIDRM);
if (sem_checkid(ns,sma,semid)) {
sem_unlock(sma);
goto out;
}
sma = sem_lock_check(ns, semid);
if (IS_ERR(sma))
return ERR_PTR(PTR_ERR(sma));

nsems = sma->sem_nsems;
ipc_rcu_getref(sma);
sem_unlock(sma);
Expand Down Expand Up @@ -1169,15 +1166,14 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
} else
un = NULL;

sma = sem_lock(ns, semid);
error=-EINVAL;
if(sma==NULL)
sma = sem_lock_check(ns, semid);
if (IS_ERR(sma)) {
error = PTR_ERR(sma);
goto out_free;
error = -EIDRM;
if (sem_checkid(ns,sma,semid))
goto out_unlock_free;
}

/*
* semid identifies are not unique - find_undo may have
* semid identifiers are not unique - find_undo may have
* allocated an undo structure, it was invalidated by an RMID
* and now a new array with received the same id. Check and retry.
*/
Expand Down Expand Up @@ -1243,7 +1239,7 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
}

sma = sem_lock(ns, semid);
if(sma==NULL) {
if (IS_ERR(sma)) {
BUG_ON(queue.prev != NULL);
error = -EIDRM;
goto out_free;
Expand Down Expand Up @@ -1343,7 +1339,7 @@ void exit_sem(struct task_struct *tsk)
if(semid == -1)
continue;
sma = sem_lock(ns, semid);
if (sma == NULL)
if (IS_ERR(sma))
continue;

if (u->semid == -1)
Expand Down
Loading

0 comments on commit 023a535

Please sign in to comment.