diff options
Diffstat (limited to 'ipc/shm.c')
-rw-r--r-- | ipc/shm.c | 90 |
1 files changed, 48 insertions, 42 deletions
@@ -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 | ||
142 | static inline int shm_checkid(struct ipc_namespace *ns, | 140 | static 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 | |
145 | static 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 | ||
150 | static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) | 151 | static 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: | |||
970 | out_nattch: | 976 | out_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) |