aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/sem.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/sem.c')
-rw-r--r--ipc/sem.c40
1 files changed, 14 insertions, 26 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index db161decb764..df98de290475 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -835,28 +835,14 @@ out_free:
835 return err; 835 return err;
836} 836}
837 837
838struct sem_setbuf { 838static inline unsigned long
839 uid_t uid; 839copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
840 gid_t gid;
841 mode_t mode;
842};
843
844static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __user *buf, int version)
845{ 840{
846 switch(version) { 841 switch(version) {
847 case IPC_64: 842 case IPC_64:
848 { 843 if (copy_from_user(out, buf, sizeof(*out)))
849 struct semid64_ds tbuf;
850
851 if(copy_from_user(&tbuf, buf, sizeof(tbuf)))
852 return -EFAULT; 844 return -EFAULT;
853
854 out->uid = tbuf.sem_perm.uid;
855 out->gid = tbuf.sem_perm.gid;
856 out->mode = tbuf.sem_perm.mode;
857
858 return 0; 845 return 0;
859 }
860 case IPC_OLD: 846 case IPC_OLD:
861 { 847 {
862 struct semid_ds tbuf_old; 848 struct semid_ds tbuf_old;
@@ -864,9 +850,9 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
864 if(copy_from_user(&tbuf_old, buf, sizeof(tbuf_old))) 850 if(copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
865 return -EFAULT; 851 return -EFAULT;
866 852
867 out->uid = tbuf_old.sem_perm.uid; 853 out->sem_perm.uid = tbuf_old.sem_perm.uid;
868 out->gid = tbuf_old.sem_perm.gid; 854 out->sem_perm.gid = tbuf_old.sem_perm.gid;
869 out->mode = tbuf_old.sem_perm.mode; 855 out->sem_perm.mode = tbuf_old.sem_perm.mode;
870 856
871 return 0; 857 return 0;
872 } 858 }
@@ -885,11 +871,11 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
885{ 871{
886 struct sem_array *sma; 872 struct sem_array *sma;
887 int err; 873 int err;
888 struct sem_setbuf uninitialized_var(setbuf); 874 struct semid64_ds semid64;
889 struct kern_ipc_perm *ipcp; 875 struct kern_ipc_perm *ipcp;
890 876
891 if(cmd == IPC_SET) { 877 if(cmd == IPC_SET) {
892 if(copy_semid_from_user (&setbuf, arg.buf, version)) 878 if (copy_semid_from_user(&semid64, arg.buf, version))
893 return -EFAULT; 879 return -EFAULT;
894 } 880 }
895 down_write(&sem_ids(ns).rw_mutex); 881 down_write(&sem_ids(ns).rw_mutex);
@@ -906,7 +892,9 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
906 goto out_unlock; 892 goto out_unlock;
907 893
908 if (cmd == IPC_SET) { 894 if (cmd == IPC_SET) {
909 err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode); 895 err = audit_ipc_set_perm(0, semid64.sem_perm.uid,
896 semid64.sem_perm.gid,
897 semid64.sem_perm.mode);
910 if (err) 898 if (err)
911 goto out_unlock; 899 goto out_unlock;
912 } 900 }
@@ -925,10 +913,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
925 freeary(ns, ipcp); 913 freeary(ns, ipcp);
926 goto out_up; 914 goto out_up;
927 case IPC_SET: 915 case IPC_SET:
928 ipcp->uid = setbuf.uid; 916 ipcp->uid = semid64.sem_perm.uid;
929 ipcp->gid = setbuf.gid; 917 ipcp->gid = semid64.sem_perm.gid;
930 ipcp->mode = (ipcp->mode & ~S_IRWXUGO) 918 ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
931 | (setbuf.mode & S_IRWXUGO); 919 | (semid64.sem_perm.mode & S_IRWXUGO);
932 sma->sem_ctime = get_seconds(); 920 sma->sem_ctime = get_seconds();
933 break; 921 break;
934 default: 922 default: