aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadia Derbey <Nadia.Derbey@bull.net>2007-10-19 02:40:51 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:44 -0400
commit023a53557ea0e987b002e9a844242ef0b0aa1eb3 (patch)
tree7f3accdd7cb1d801607bf71e56b9b99e9c7ff7ca
parent637c36634029e4e7c81112796dafc32d56355b4a (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>
-rw-r--r--ipc/msg.c62
-rw-r--r--ipc/sem.c70
-rw-r--r--ipc/shm.c90
-rw-r--r--ipc/util.c23
-rw-r--r--ipc/util.h43
5 files changed, 152 insertions, 136 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index c2ee26f01055..74e672035675 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -73,10 +73,7 @@ static struct ipc_ids init_msg_ids;
73 73
74#define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS])) 74#define msg_ids(ns) (*((ns)->ids[IPC_MSG_IDS]))
75 75
76#define msg_lock(ns, id) ((struct msg_queue*)ipc_lock(&msg_ids(ns), id))
77#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) 76#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm)
78#define msg_checkid(ns, msq, msgid) \
79 ipc_checkid(&msg_ids(ns), &msq->q_perm, msgid)
80#define msg_buildid(ns, id, seq) \ 77#define msg_buildid(ns, id, seq) \
81 ipc_buildid(&msg_ids(ns), id, seq) 78 ipc_buildid(&msg_ids(ns), id, seq)
82 79
@@ -139,6 +136,17 @@ void __init msg_init(void)
139 IPC_MSG_IDS, sysvipc_msg_proc_show); 136 IPC_MSG_IDS, sysvipc_msg_proc_show);
140} 137}
141 138
139static inline struct msg_queue *msg_lock(struct ipc_namespace *ns, int id)
140{
141 return (struct msg_queue *) ipc_lock(&msg_ids(ns), id);
142}
143
144static inline struct msg_queue *msg_lock_check(struct ipc_namespace *ns,
145 int id)
146{
147 return (struct msg_queue *) ipc_lock_check(&msg_ids(ns), id);
148}
149
142static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s) 150static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
143{ 151{
144 ipc_rmid(&msg_ids(ns), &s->q_perm); 152 ipc_rmid(&msg_ids(ns), &s->q_perm);
@@ -445,18 +453,15 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
445 if (!buf) 453 if (!buf)
446 return -EFAULT; 454 return -EFAULT;
447 455
448 memset(&tbuf, 0, sizeof(tbuf));
449
450 msq = msg_lock(ns, msqid);
451 if (msq == NULL)
452 return -EINVAL;
453
454 if (cmd == MSG_STAT) { 456 if (cmd == MSG_STAT) {
457 msq = msg_lock(ns, msqid);
458 if (IS_ERR(msq))
459 return PTR_ERR(msq);
455 success_return = msq->q_perm.id; 460 success_return = msq->q_perm.id;
456 } else { 461 } else {
457 err = -EIDRM; 462 msq = msg_lock_check(ns, msqid);
458 if (msg_checkid(ns, msq, msqid)) 463 if (IS_ERR(msq))
459 goto out_unlock; 464 return PTR_ERR(msq);
460 success_return = 0; 465 success_return = 0;
461 } 466 }
462 err = -EACCES; 467 err = -EACCES;
@@ -467,6 +472,8 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
467 if (err) 472 if (err)
468 goto out_unlock; 473 goto out_unlock;
469 474
475 memset(&tbuf, 0, sizeof(tbuf));
476
470 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); 477 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
471 tbuf.msg_stime = msq->q_stime; 478 tbuf.msg_stime = msq->q_stime;
472 tbuf.msg_rtime = msq->q_rtime; 479 tbuf.msg_rtime = msq->q_rtime;
@@ -494,14 +501,12 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
494 } 501 }
495 502
496 mutex_lock(&msg_ids(ns).mutex); 503 mutex_lock(&msg_ids(ns).mutex);
497 msq = msg_lock(ns, msqid); 504 msq = msg_lock_check(ns, msqid);
498 err = -EINVAL; 505 if (IS_ERR(msq)) {
499 if (msq == NULL) 506 err = PTR_ERR(msq);
500 goto out_up; 507 goto out_up;
508 }
501 509
502 err = -EIDRM;
503 if (msg_checkid(ns, msq, msqid))
504 goto out_unlock_up;
505 ipcp = &msq->q_perm; 510 ipcp = &msq->q_perm;
506 511
507 err = audit_ipc_obj(ipcp); 512 err = audit_ipc_obj(ipcp);
@@ -644,14 +649,11 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
644 msg->m_type = mtype; 649 msg->m_type = mtype;
645 msg->m_ts = msgsz; 650 msg->m_ts = msgsz;
646 651
647 msq = msg_lock(ns, msqid); 652 msq = msg_lock_check(ns, msqid);
648 err = -EINVAL; 653 if (IS_ERR(msq)) {
649 if (msq == NULL) 654 err = PTR_ERR(msq);
650 goto out_free; 655 goto out_free;
651 656 }
652 err= -EIDRM;
653 if (msg_checkid(ns, msq, msqid))
654 goto out_unlock_free;
655 657
656 for (;;) { 658 for (;;) {
657 struct msg_sender s; 659 struct msg_sender s;
@@ -758,13 +760,9 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
758 mode = convert_mode(&msgtyp, msgflg); 760 mode = convert_mode(&msgtyp, msgflg);
759 ns = current->nsproxy->ipc_ns; 761 ns = current->nsproxy->ipc_ns;
760 762
761 msq = msg_lock(ns, msqid); 763 msq = msg_lock_check(ns, msqid);
762 if (msq == NULL) 764 if (IS_ERR(msq))
763 return -EINVAL; 765 return PTR_ERR(msq);
764
765 msg = ERR_PTR(-EIDRM);
766 if (msg_checkid(ns, msq, msqid))
767 goto out_unlock;
768 766
769 for (;;) { 767 for (;;) {
770 struct msg_receiver msr_d; 768 struct msg_receiver msr_d;
diff --git a/ipc/sem.c b/ipc/sem.c
index 6af226af0b90..673d63da52c6 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -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
177static 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
182static 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
178static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) 188static 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)
diff --git a/ipc/shm.c b/ipc/shm.c
index 8cf1cf3d5bec..8241264941a2 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -59,8 +59,6 @@ static struct ipc_ids init_shm_ids;
59 59
60#define shm_ids(ns) (*((ns)->ids[IPC_SHM_IDS])) 60#define shm_ids(ns) (*((ns)->ids[IPC_SHM_IDS]))
61 61
62#define shm_lock(ns, id) \
63 ((struct shmid_kernel*)ipc_lock(&shm_ids(ns),id))
64#define shm_unlock(shp) \ 62#define shm_unlock(shp) \
65 ipc_unlock(&(shp)->shm_perm) 63 ipc_unlock(&(shp)->shm_perm)
66#define shm_buildid(ns, id, seq) \ 64#define shm_buildid(ns, id, seq) \
@@ -139,12 +137,15 @@ void __init shm_init (void)
139 IPC_SHM_IDS, sysvipc_shm_proc_show); 137 IPC_SHM_IDS, sysvipc_shm_proc_show);
140} 138}
141 139
142static inline int shm_checkid(struct ipc_namespace *ns, 140static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
143 struct shmid_kernel *s, int id)
144{ 141{
145 if (ipc_checkid(&shm_ids(ns), &s->shm_perm, id)) 142 return (struct shmid_kernel *) ipc_lock(&shm_ids(ns), id);
146 return -EIDRM; 143}
147 return 0; 144
145static inline struct shmid_kernel *shm_lock_check(struct ipc_namespace *ns,
146 int id)
147{
148 return (struct shmid_kernel *) ipc_lock_check(&shm_ids(ns), id);
148} 149}
149 150
150static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) 151static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s)
@@ -167,7 +168,7 @@ static void shm_open(struct vm_area_struct *vma)
167 struct shmid_kernel *shp; 168 struct shmid_kernel *shp;
168 169
169 shp = shm_lock(sfd->ns, sfd->id); 170 shp = shm_lock(sfd->ns, sfd->id);
170 BUG_ON(!shp); 171 BUG_ON(IS_ERR(shp));
171 shp->shm_atim = get_seconds(); 172 shp->shm_atim = get_seconds();
172 shp->shm_lprid = task_tgid_vnr(current); 173 shp->shm_lprid = task_tgid_vnr(current);
173 shp->shm_nattch++; 174 shp->shm_nattch++;
@@ -213,7 +214,7 @@ static void shm_close(struct vm_area_struct *vma)
213 mutex_lock(&shm_ids(ns).mutex); 214 mutex_lock(&shm_ids(ns).mutex);
214 /* remove from the list of attaches of the shm segment */ 215 /* remove from the list of attaches of the shm segment */
215 shp = shm_lock(ns, sfd->id); 216 shp = shm_lock(ns, sfd->id);
216 BUG_ON(!shp); 217 BUG_ON(IS_ERR(shp));
217 shp->shm_lprid = task_tgid_vnr(current); 218 shp->shm_lprid = task_tgid_vnr(current);
218 shp->shm_dtim = get_seconds(); 219 shp->shm_dtim = get_seconds();
219 shp->shm_nattch--; 220 shp->shm_nattch--;
@@ -662,17 +663,25 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
662 { 663 {
663 struct shmid64_ds tbuf; 664 struct shmid64_ds tbuf;
664 int result; 665 int result;
665 memset(&tbuf, 0, sizeof(tbuf)); 666
666 shp = shm_lock(ns, shmid); 667 if (!buf) {
667 if(shp==NULL) { 668 err = -EFAULT;
668 err = -EINVAL;
669 goto out; 669 goto out;
670 } else if (cmd == SHM_STAT) { 670 }
671
672 if (cmd == SHM_STAT) {
673 shp = shm_lock(ns, shmid);
674 if (IS_ERR(shp)) {
675 err = PTR_ERR(shp);
676 goto out;
677 }
671 result = shp->shm_perm.id; 678 result = shp->shm_perm.id;
672 } else { 679 } else {
673 err = shm_checkid(ns, shp,shmid); 680 shp = shm_lock_check(ns, shmid);
674 if(err) 681 if (IS_ERR(shp)) {
675 goto out_unlock; 682 err = PTR_ERR(shp);
683 goto out;
684 }
676 result = 0; 685 result = 0;
677 } 686 }
678 err=-EACCES; 687 err=-EACCES;
@@ -681,6 +690,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
681 err = security_shm_shmctl(shp, cmd); 690 err = security_shm_shmctl(shp, cmd);
682 if (err) 691 if (err)
683 goto out_unlock; 692 goto out_unlock;
693 memset(&tbuf, 0, sizeof(tbuf));
684 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); 694 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
685 tbuf.shm_segsz = shp->shm_segsz; 695 tbuf.shm_segsz = shp->shm_segsz;
686 tbuf.shm_atime = shp->shm_atim; 696 tbuf.shm_atime = shp->shm_atim;
@@ -699,14 +709,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
699 case SHM_LOCK: 709 case SHM_LOCK:
700 case SHM_UNLOCK: 710 case SHM_UNLOCK:
701 { 711 {
702 shp = shm_lock(ns, shmid); 712 shp = shm_lock_check(ns, shmid);
703 if(shp==NULL) { 713 if (IS_ERR(shp)) {
704 err = -EINVAL; 714 err = PTR_ERR(shp);
705 goto out; 715 goto out;
706 } 716 }
707 err = shm_checkid(ns, shp,shmid);
708 if(err)
709 goto out_unlock;
710 717
711 err = audit_ipc_obj(&(shp->shm_perm)); 718 err = audit_ipc_obj(&(shp->shm_perm));
712 if (err) 719 if (err)
@@ -756,13 +763,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
756 * the name away when the usage hits zero. 763 * the name away when the usage hits zero.
757 */ 764 */
758 mutex_lock(&shm_ids(ns).mutex); 765 mutex_lock(&shm_ids(ns).mutex);
759 shp = shm_lock(ns, shmid); 766 shp = shm_lock_check(ns, shmid);
760 err = -EINVAL; 767 if (IS_ERR(shp)) {
761 if (shp == NULL) 768 err = PTR_ERR(shp);
762 goto out_up; 769 goto out_up;
763 err = shm_checkid(ns, shp, shmid); 770 }
764 if(err)
765 goto out_unlock_up;
766 771
767 err = audit_ipc_obj(&(shp->shm_perm)); 772 err = audit_ipc_obj(&(shp->shm_perm));
768 if (err) 773 if (err)
@@ -786,18 +791,21 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
786 791
787 case IPC_SET: 792 case IPC_SET:
788 { 793 {
794 if (!buf) {
795 err = -EFAULT;
796 goto out;
797 }
798
789 if (copy_shmid_from_user (&setbuf, buf, version)) { 799 if (copy_shmid_from_user (&setbuf, buf, version)) {
790 err = -EFAULT; 800 err = -EFAULT;
791 goto out; 801 goto out;
792 } 802 }
793 mutex_lock(&shm_ids(ns).mutex); 803 mutex_lock(&shm_ids(ns).mutex);
794 shp = shm_lock(ns, shmid); 804 shp = shm_lock_check(ns, shmid);
795 err=-EINVAL; 805 if (IS_ERR(shp)) {
796 if(shp==NULL) 806 err = PTR_ERR(shp);
797 goto out_up; 807 goto out_up;
798 err = shm_checkid(ns, shp,shmid); 808 }
799 if(err)
800 goto out_unlock_up;
801 err = audit_ipc_obj(&(shp->shm_perm)); 809 err = audit_ipc_obj(&(shp->shm_perm));
802 if (err) 810 if (err)
803 goto out_unlock_up; 811 goto out_unlock_up;
@@ -903,13 +911,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
903 * additional creator id... 911 * additional creator id...
904 */ 912 */
905 ns = current->nsproxy->ipc_ns; 913 ns = current->nsproxy->ipc_ns;
906 shp = shm_lock(ns, shmid); 914 shp = shm_lock_check(ns, shmid);
907 if(shp == NULL) 915 if (IS_ERR(shp)) {
916 err = PTR_ERR(shp);
908 goto out; 917 goto out;
909 918 }
910 err = shm_checkid(ns, shp,shmid);
911 if (err)
912 goto out_unlock;
913 919
914 err = -EACCES; 920 err = -EACCES;
915 if (ipcperms(&shp->shm_perm, acc_mode)) 921 if (ipcperms(&shp->shm_perm, acc_mode))
@@ -970,7 +976,7 @@ invalid:
970out_nattch: 976out_nattch:
971 mutex_lock(&shm_ids(ns).mutex); 977 mutex_lock(&shm_ids(ns).mutex);
972 shp = shm_lock(ns, shmid); 978 shp = shm_lock(ns, shmid);
973 BUG_ON(!shp); 979 BUG_ON(IS_ERR(shp));
974 shp->shm_nattch--; 980 shp->shm_nattch--;
975 if(shp->shm_nattch == 0 && 981 if(shp->shm_nattch == 0 &&
976 shp->shm_perm.mode & SHM_DEST) 982 shp->shm_perm.mode & SHM_DEST)
diff --git a/ipc/util.c b/ipc/util.c
index e72865f677a7..9b0c4e7753af 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -678,7 +678,7 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
678 out = idr_find(&ids->ipcs_idr, lid); 678 out = idr_find(&ids->ipcs_idr, lid);
679 if (out == NULL) { 679 if (out == NULL) {
680 rcu_read_unlock(); 680 rcu_read_unlock();
681 return NULL; 681 return ERR_PTR(-EINVAL);
682 } 682 }
683 683
684 spin_lock(&out->lock); 684 spin_lock(&out->lock);
@@ -689,36 +689,17 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
689 if (out->deleted) { 689 if (out->deleted) {
690 spin_unlock(&out->lock); 690 spin_unlock(&out->lock);
691 rcu_read_unlock(); 691 rcu_read_unlock();
692 return NULL; 692 return ERR_PTR(-EINVAL);
693 } 693 }
694 694
695 return out; 695 return out;
696} 696}
697 697
698void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
699{
700 rcu_read_lock();
701 spin_lock(&perm->lock);
702}
703
704void ipc_unlock(struct kern_ipc_perm* perm)
705{
706 spin_unlock(&perm->lock);
707 rcu_read_unlock();
708}
709
710int ipc_buildid(struct ipc_ids* ids, int id, int seq) 698int ipc_buildid(struct ipc_ids* ids, int id, int seq)
711{ 699{
712 return SEQ_MULTIPLIER*seq + id; 700 return SEQ_MULTIPLIER*seq + id;
713} 701}
714 702
715int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid)
716{
717 if(uid/SEQ_MULTIPLIER != ipcp->seq)
718 return 1;
719 return 0;
720}
721
722#ifdef __ARCH_WANT_IPC_PARSE_VERSION 703#ifdef __ARCH_WANT_IPC_PARSE_VERSION
723 704
724 705
diff --git a/ipc/util.h b/ipc/util.h
index 1546eda7d99e..c4b0a9865bf5 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -11,6 +11,7 @@
11#define _IPC_UTIL_H 11#define _IPC_UTIL_H
12 12
13#include <linux/idr.h> 13#include <linux/idr.h>
14#include <linux/err.h>
14 15
15#define USHRT_MAX 0xffff 16#define USHRT_MAX 0xffff
16#define SEQ_MULTIPLIER (IPCMNI) 17#define SEQ_MULTIPLIER (IPCMNI)
@@ -103,11 +104,8 @@ void* ipc_rcu_alloc(int size);
103void ipc_rcu_getref(void *ptr); 104void ipc_rcu_getref(void *ptr);
104void ipc_rcu_putref(void *ptr); 105void ipc_rcu_putref(void *ptr);
105 106
106struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id); 107struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
107void ipc_lock_by_ptr(struct kern_ipc_perm *ipcp);
108void ipc_unlock(struct kern_ipc_perm* perm);
109int ipc_buildid(struct ipc_ids* ids, int id, int seq); 108int ipc_buildid(struct ipc_ids* ids, int id, int seq);
110int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid);
111 109
112void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out); 110void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
113void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out); 111void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
@@ -127,6 +125,43 @@ extern int ipcget_new(struct ipc_namespace *, struct ipc_ids *,
127extern int ipcget_public(struct ipc_namespace *, struct ipc_ids *, 125extern int ipcget_public(struct ipc_namespace *, struct ipc_ids *,
128 struct ipc_ops *, struct ipc_params *); 126 struct ipc_ops *, struct ipc_params *);
129 127
128static inline int ipc_checkid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp,
129 int uid)
130{
131 if (uid / SEQ_MULTIPLIER != ipcp->seq)
132 return 1;
133 return 0;
134}
135
136static inline void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
137{
138 rcu_read_lock();
139 spin_lock(&perm->lock);
140}
141
142static inline void ipc_unlock(struct kern_ipc_perm *perm)
143{
144 spin_unlock(&perm->lock);
145 rcu_read_unlock();
146}
147
148static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids,
149 int id)
150{
151 struct kern_ipc_perm *out;
152
153 out = ipc_lock(ids, id);
154 if (IS_ERR(out))
155 return out;
156
157 if (ipc_checkid(ids, out, id)) {
158 ipc_unlock(out);
159 return ERR_PTR(-EIDRM);
160 }
161
162 return out;
163}
164
130static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, 165static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
131 struct ipc_ops *ops, struct ipc_params *params) 166 struct ipc_ops *ops, struct ipc_params *params)
132{ 167{