]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/sysv_sem.c
xnu-2422.110.17.tar.gz
[apple/xnu.git] / bsd / kern / sysv_sem.c
index ed43ec893ab289f8bb21494ee1abec7bfbd5525b..f98530962b733037533b7628b432132c04c3ef32 100644 (file)
@@ -444,7 +444,8 @@ grow_sem_pool(int new_pool_size)
        /* Update our id structures to point to the new semaphores */
        for(i = 0; i < seminfo.semmni; i++) {
                if (sema[i].u.sem_perm.mode & SEM_ALLOC)  /* ID in use */
-                       sema[i].u.sem_base += (new_sem_pool - sem_pool);
+                       sema[i].u.sem_base = new_sem_pool + 
+                               (sema[i].u.sem_base - sem_pool);
        }
 
        sem_free = sem_pool;
@@ -774,10 +775,12 @@ semctl(struct proc *p, struct semctl_args *uap, int32_t *retval)
 
                if (IS_64BIT_PROCESS(p)) {
                        struct user64_semid_ds semid_ds64;
+                       bzero(&semid_ds64, sizeof(semid_ds64));
                        semid_ds_kernelto64(&semakptr->u, &semid_ds64);
                        eval = copyout(&semid_ds64, user_arg.buf, sizeof(semid_ds64));
                } else {
                        struct user32_semid_ds semid_ds32;
+                       bzero(&semid_ds32, sizeof(semid_ds32));
                        semid_ds_kernelto32(&semakptr->u, &semid_ds32);
                        eval = copyout(&semid_ds32, user_arg.buf, sizeof(semid_ds32));
                }
@@ -853,12 +856,27 @@ semctl(struct proc *p, struct semctl_args *uap, int32_t *retval)
                        eval = EINVAL;
                        goto semctlout;
                }
+               
                /*
                 * Cast down a pointer instead of using 'val' member directly
                 * to avoid introducing endieness and a pad field into the
                 * header file.  Ugly, but it works.
                 */
-               semakptr->u.sem_base[semnum].semval = CAST_DOWN_EXPLICIT(int,user_arg.buf);
+               u_int newsemval = CAST_DOWN_EXPLICIT(u_int, user_arg.buf);
+               
+               /*
+                * The check is being performed as unsigned values to match 
+                * eventual destination
+                */ 
+               if (newsemval > (u_int)seminfo.semvmx)
+               {
+#ifdef SEM_DEBUG
+                       printf("Out of range sem value for set\n");
+#endif
+                       eval = ERANGE;
+                       goto semctlout;
+               }
+               semakptr->u.sem_base[semnum].semval = newsemval;
                semakptr->u.sem_base[semnum].sempid = p->p_pid;
                /* XXX scottl Should there be a MAC call here? */
                semundo_clear(semid, semnum);
@@ -1044,7 +1062,7 @@ semop(struct proc *p, struct semop_args *uap, int32_t *retval)
 {
        int semid = uap->semid;
        int nsops = uap->nsops;
-       struct sembuf sops[MAX_SOPS];
+       struct sembuf sops[seminfo.semopm];
        register struct semid_kernel *semakptr;
        register struct sembuf *sopptr = NULL;  /* protected by 'semptr' */
        register struct sem *semptr = NULL;     /* protected by 'if' */
@@ -1084,14 +1102,15 @@ semop(struct proc *p, struct semop_args *uap, int32_t *retval)
                goto semopout;
        }
 
-       if (nsops < 0 || nsops > MAX_SOPS) {
+       if (nsops < 0 || nsops > seminfo.semopm) {
 #ifdef SEM_DEBUG
-               printf("too many sops (max=%d, nsops=%d)\n", MAX_SOPS, nsops);
+               printf("too many sops (max=%d, nsops=%d)\n",
+                   seminfo.semopm, nsops);
 #endif
                eval = E2BIG;
                goto semopout;
        }
-
+       
        /*  OK for LP64, since sizeof(struct sembuf) is currently invariant */
        if ((eval = copyin(uap->sops, &sops, nsops * sizeof(struct sembuf))) != 0) {
 #ifdef SEM_DEBUG
@@ -1634,9 +1653,11 @@ IPCS_sem_sysctl(__unused struct sysctl_oid *oidp, __unused void *arg1,
                 * descriptor to a 32 bit user one.
                 */
                if (!IS_64BIT_PROCESS(p)) {
+                       bzero(&semid_ds32, sizeof(semid_ds32));
                        semid_ds_kernelto32(semid_dsp, &semid_ds32);
                        semid_dsp = &semid_ds32;
                } else {
+                       bzero(&semid_ds64, sizeof(semid_ds64));
                        semid_ds_kernelto64(semid_dsp, &semid_ds64);
                        semid_dsp = &semid_ds64;
                }