diff options
Diffstat (limited to 'ipc/sem.c')
-rw-r--r-- | ipc/sem.c | 40 |
1 files changed, 14 insertions, 26 deletions
@@ -835,28 +835,14 @@ out_free: | |||
835 | return err; | 835 | return err; |
836 | } | 836 | } |
837 | 837 | ||
838 | struct sem_setbuf { | 838 | static inline unsigned long |
839 | uid_t uid; | 839 | copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version) |
840 | gid_t gid; | ||
841 | mode_t mode; | ||
842 | }; | ||
843 | |||
844 | static 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: |