diff options
author | Nadia Derbey <Nadia.Derbey@bull.net> | 2007-10-19 02:40:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:44 -0400 |
commit | 023a53557ea0e987b002e9a844242ef0b0aa1eb3 (patch) | |
tree | 7f3accdd7cb1d801607bf71e56b9b99e9c7ff7ca /ipc/sem.c | |
parent | 637c36634029e4e7c81112796dafc32d56355b4a (diff) |
ipc: integrate ipc_checkid() into ipc_lock()
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().
[akpm@linux-foundation.org: build fix]
[akpm@linux-foundation.org: fix RCU locking]
Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/sem.c')
-rw-r--r-- | ipc/sem.c | 70 |
1 files changed, 33 insertions, 37 deletions
@@ -88,7 +88,6 @@ | |||
88 | 88 | ||
89 | #define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS])) | 89 | #define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS])) |
90 | 90 | ||
91 | #define sem_lock(ns, id) ((struct sem_array*)ipc_lock(&sem_ids(ns), id)) | ||
92 | #define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm) | 91 | #define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm) |
93 | #define sem_checkid(ns, sma, semid) \ | 92 | #define sem_checkid(ns, sma, semid) \ |
94 | ipc_checkid(&sem_ids(ns),&sma->sem_perm,semid) | 93 | ipc_checkid(&sem_ids(ns),&sma->sem_perm,semid) |
@@ -175,6 +174,17 @@ void __init sem_init (void) | |||
175 | IPC_SEM_IDS, sysvipc_sem_proc_show); | 174 | IPC_SEM_IDS, sysvipc_sem_proc_show); |
176 | } | 175 | } |
177 | 176 | ||
177 | static inline struct sem_array *sem_lock(struct ipc_namespace *ns, int id) | ||
178 | { | ||
179 | return (struct sem_array *) ipc_lock(&sem_ids(ns), id); | ||
180 | } | ||
181 | |||
182 | static inline struct sem_array *sem_lock_check(struct ipc_namespace *ns, | ||
183 | int id) | ||
184 | { | ||
185 | return (struct sem_array *) ipc_lock_check(&sem_ids(ns), id); | ||
186 | } | ||
187 | |||
178 | static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) | 188 | static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) |
179 | { | 189 | { |
180 | ipc_rmid(&sem_ids(ns), &s->sem_perm); | 190 | ipc_rmid(&sem_ids(ns), &s->sem_perm); |
@@ -599,11 +609,9 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum, | |||
599 | struct semid64_ds tbuf; | 609 | struct semid64_ds tbuf; |
600 | int id; | 610 | int id; |
601 | 611 | ||
602 | memset(&tbuf,0,sizeof(tbuf)); | ||
603 | |||
604 | sma = sem_lock(ns, semid); | 612 | sma = sem_lock(ns, semid); |
605 | if(sma == NULL) | 613 | if (IS_ERR(sma)) |
606 | return -EINVAL; | 614 | return PTR_ERR(sma); |
607 | 615 | ||
608 | err = -EACCES; | 616 | err = -EACCES; |
609 | if (ipcperms (&sma->sem_perm, S_IRUGO)) | 617 | if (ipcperms (&sma->sem_perm, S_IRUGO)) |
@@ -615,6 +623,8 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum, | |||
615 | 623 | ||
616 | id = sma->sem_perm.id; | 624 | id = sma->sem_perm.id; |
617 | 625 | ||
626 | memset(&tbuf, 0, sizeof(tbuf)); | ||
627 | |||
618 | kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); | 628 | kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); |
619 | tbuf.sem_otime = sma->sem_otime; | 629 | tbuf.sem_otime = sma->sem_otime; |
620 | tbuf.sem_ctime = sma->sem_ctime; | 630 | tbuf.sem_ctime = sma->sem_ctime; |
@@ -643,16 +653,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum, | |||
643 | ushort* sem_io = fast_sem_io; | 653 | ushort* sem_io = fast_sem_io; |
644 | int nsems; | 654 | int nsems; |
645 | 655 | ||
646 | sma = sem_lock(ns, semid); | 656 | sma = sem_lock_check(ns, semid); |
647 | if(sma==NULL) | 657 | if (IS_ERR(sma)) |
648 | return -EINVAL; | 658 | return PTR_ERR(sma); |
649 | 659 | ||
650 | nsems = sma->sem_nsems; | 660 | nsems = sma->sem_nsems; |
651 | 661 | ||
652 | err=-EIDRM; | ||
653 | if (sem_checkid(ns,sma,semid)) | ||
654 | goto out_unlock; | ||
655 | |||
656 | err = -EACCES; | 662 | err = -EACCES; |
657 | if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO)) | 663 | if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO)) |
658 | goto out_unlock; | 664 | goto out_unlock; |
@@ -864,14 +870,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, | |||
864 | if(copy_semid_from_user (&setbuf, arg.buf, version)) | 870 | if(copy_semid_from_user (&setbuf, arg.buf, version)) |
865 | return -EFAULT; | 871 | return -EFAULT; |
866 | } | 872 | } |
867 | sma = sem_lock(ns, semid); | 873 | sma = sem_lock_check(ns, semid); |
868 | if(sma==NULL) | 874 | if (IS_ERR(sma)) |
869 | return -EINVAL; | 875 | return PTR_ERR(sma); |
870 | 876 | ||
871 | if (sem_checkid(ns,sma,semid)) { | ||
872 | err=-EIDRM; | ||
873 | goto out_unlock; | ||
874 | } | ||
875 | ipcp = &sma->sem_perm; | 877 | ipcp = &sma->sem_perm; |
876 | 878 | ||
877 | err = audit_ipc_obj(ipcp); | 879 | err = audit_ipc_obj(ipcp); |
@@ -1055,15 +1057,10 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid) | |||
1055 | goto out; | 1057 | goto out; |
1056 | 1058 | ||
1057 | /* no undo structure around - allocate one. */ | 1059 | /* no undo structure around - allocate one. */ |
1058 | sma = sem_lock(ns, semid); | 1060 | sma = sem_lock_check(ns, semid); |
1059 | un = ERR_PTR(-EINVAL); | 1061 | if (IS_ERR(sma)) |
1060 | if(sma==NULL) | 1062 | return ERR_PTR(PTR_ERR(sma)); |
1061 | goto out; | 1063 | |
1062 | un = ERR_PTR(-EIDRM); | ||
1063 | if (sem_checkid(ns,sma,semid)) { | ||
1064 | sem_unlock(sma); | ||
1065 | goto out; | ||
1066 | } | ||
1067 | nsems = sma->sem_nsems; | 1064 | nsems = sma->sem_nsems; |
1068 | ipc_rcu_getref(sma); | 1065 | ipc_rcu_getref(sma); |
1069 | sem_unlock(sma); | 1066 | sem_unlock(sma); |
@@ -1169,15 +1166,14 @@ retry_undos: | |||
1169 | } else | 1166 | } else |
1170 | un = NULL; | 1167 | un = NULL; |
1171 | 1168 | ||
1172 | sma = sem_lock(ns, semid); | 1169 | sma = sem_lock_check(ns, semid); |
1173 | error=-EINVAL; | 1170 | if (IS_ERR(sma)) { |
1174 | if(sma==NULL) | 1171 | error = PTR_ERR(sma); |
1175 | goto out_free; | 1172 | goto out_free; |
1176 | error = -EIDRM; | 1173 | } |
1177 | if (sem_checkid(ns,sma,semid)) | 1174 | |
1178 | goto out_unlock_free; | ||
1179 | /* | 1175 | /* |
1180 | * semid identifies are not unique - find_undo may have | 1176 | * semid identifiers are not unique - find_undo may have |
1181 | * allocated an undo structure, it was invalidated by an RMID | 1177 | * allocated an undo structure, it was invalidated by an RMID |
1182 | * and now a new array with received the same id. Check and retry. | 1178 | * and now a new array with received the same id. Check and retry. |
1183 | */ | 1179 | */ |
@@ -1243,7 +1239,7 @@ retry_undos: | |||
1243 | } | 1239 | } |
1244 | 1240 | ||
1245 | sma = sem_lock(ns, semid); | 1241 | sma = sem_lock(ns, semid); |
1246 | if(sma==NULL) { | 1242 | if (IS_ERR(sma)) { |
1247 | BUG_ON(queue.prev != NULL); | 1243 | BUG_ON(queue.prev != NULL); |
1248 | error = -EIDRM; | 1244 | error = -EIDRM; |
1249 | goto out_free; | 1245 | goto out_free; |
@@ -1343,7 +1339,7 @@ void exit_sem(struct task_struct *tsk) | |||
1343 | if(semid == -1) | 1339 | if(semid == -1) |
1344 | continue; | 1340 | continue; |
1345 | sma = sem_lock(ns, semid); | 1341 | sma = sem_lock(ns, semid); |
1346 | if (sma == NULL) | 1342 | if (IS_ERR(sma)) |
1347 | continue; | 1343 | continue; |
1348 | 1344 | ||
1349 | if (u->semid == -1) | 1345 | if (u->semid == -1) |