aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/sem.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 1b5ae352cde4..77162eddcbfc 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -875,6 +875,11 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
875 } 875 }
876} 876}
877 877
878/*
879 * This function handles some semctl commands which require the rw_mutex
880 * to be held in write mode.
881 * NOTE: no locks must be held, the rw_mutex is taken inside this function.
882 */
878static int semctl_down(struct ipc_namespace *ns, int semid, int semnum, 883static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
879 int cmd, int version, union semun arg) 884 int cmd, int version, union semun arg)
880{ 885{
@@ -887,9 +892,12 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
887 if(copy_semid_from_user (&setbuf, arg.buf, version)) 892 if(copy_semid_from_user (&setbuf, arg.buf, version))
888 return -EFAULT; 893 return -EFAULT;
889 } 894 }
895 down_write(&sem_ids(ns).rw_mutex);
890 sma = sem_lock_check_down(ns, semid); 896 sma = sem_lock_check_down(ns, semid);
891 if (IS_ERR(sma)) 897 if (IS_ERR(sma)) {
892 return PTR_ERR(sma); 898 err = PTR_ERR(sma);
899 goto out_up;
900 }
893 901
894 ipcp = &sma->sem_perm; 902 ipcp = &sma->sem_perm;
895 903
@@ -915,26 +923,22 @@ static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
915 switch(cmd){ 923 switch(cmd){
916 case IPC_RMID: 924 case IPC_RMID:
917 freeary(ns, ipcp); 925 freeary(ns, ipcp);
918 err = 0; 926 goto out_up;
919 break;
920 case IPC_SET: 927 case IPC_SET:
921 ipcp->uid = setbuf.uid; 928 ipcp->uid = setbuf.uid;
922 ipcp->gid = setbuf.gid; 929 ipcp->gid = setbuf.gid;
923 ipcp->mode = (ipcp->mode & ~S_IRWXUGO) 930 ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
924 | (setbuf.mode & S_IRWXUGO); 931 | (setbuf.mode & S_IRWXUGO);
925 sma->sem_ctime = get_seconds(); 932 sma->sem_ctime = get_seconds();
926 sem_unlock(sma);
927 err = 0;
928 break; 933 break;
929 default: 934 default:
930 sem_unlock(sma);
931 err = -EINVAL; 935 err = -EINVAL;
932 break;
933 } 936 }
934 return err;
935 937
936out_unlock: 938out_unlock:
937 sem_unlock(sma); 939 sem_unlock(sma);
940out_up:
941 up_write(&sem_ids(ns).rw_mutex);
938 return err; 942 return err;
939} 943}
940 944
@@ -968,9 +972,7 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
968 return err; 972 return err;
969 case IPC_RMID: 973 case IPC_RMID:
970 case IPC_SET: 974 case IPC_SET:
971 down_write(&sem_ids(ns).rw_mutex);
972 err = semctl_down(ns,semid,semnum,cmd,version,arg); 975 err = semctl_down(ns,semid,semnum,cmd,version,arg);
973 up_write(&sem_ids(ns).rw_mutex);
974 return err; 976 return err;
975 default: 977 default:
976 return -EINVAL; 978 return -EINVAL;