]> git.hungrycats.org Git - linux/commitdiff
[PATCH] s390: semtimedop.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 1 Jul 2003 09:16:39 +0000 (02:16 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Tue, 1 Jul 2003 09:16:39 +0000 (02:16 -0700)
Fix SEMTIMEDOP operation in sys_ipc. Patch by Ernie Petrides.

arch/s390/kernel/compat_linux.c
arch/s390/kernel/sys_s390.c

index 05f6e5caffc9d3c31aac2433671f4d082611e7aa..ea603c4820dad555c86bbd588dc10d82cdaae2a4 100644 (file)
@@ -373,12 +373,45 @@ struct shmid64_ds32 {
        unsigned int            __unused5;
 };
 
-                                                        
-/*
- * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
- *
- * This is really horribly ugly.
- */
+extern int sem_ctls[];
+#define sc_semopm      (sem_ctls[2])
+#define SEMOPM_FAST    64  /* ~ 372 bytes on stack */
+
+static long
+do_sys32_semtimedop (int semid, struct sembuf *tsops, int nsops,
+                    struct compat_timespec *timeout32)
+{
+       struct sembuf *sops, fast_sops[SEMOPM_FAST];
+       struct timespec t;
+       mm_segment_t oldfs;
+       long ret;
+
+       /* parameter checking precedence should mirror sys_semtimedop() */
+       if (nsops < 1 || semid < 0)
+               return -EINVAL;
+       if (nsops > sc_semopm)
+               return -E2BIG;
+       if (nsops <= SEMOPM_FAST)
+               sops = fast_sops;
+       else {
+               sops = kmalloc(nsops * sizeof(*sops), GFP_KERNEL);
+               if (sops == NULL)
+                       return -ENOMEM;
+       }
+       if (copy_from_user(sops, tsops, nsops * sizeof(*tsops)) ||
+           get_compat_timespec(&t, timeout32))
+               ret = -EFAULT;
+       else {
+               oldfs = get_fs();
+               set_fs(KERNEL_DS);
+               ret = sys_semtimedop(semid, sops, nsops, &t);
+               set_fs(oldfs);
+       }
+       if (sops != fast_sops)
+               kfree(sops);
+       return ret;
+}
+
 #define IPCOP_MASK(__x)        (1UL << (__x))
 static int do_sys32_semctl(int first, int second, int third, void *uptr)
 {
@@ -763,7 +796,12 @@ out:
        return err;
 }
 
-asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+/*
+ * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr)
 {
        int version, err;
 
@@ -773,11 +811,22 @@ asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u
        if(version)
                return -EINVAL;
 
-       if (call <= SEMCTL)
+       if (call <= SEMTIMEDOP)
                switch (call) {
+               case SEMTIMEDOP:
+                       if (third) {
+                               err = do_sys32_semtimedop(first,
+                                       (struct sembuf *)AA(ptr),
+                                       second,
+                                       (struct compat_timespec *)
+                                               AA((u32)third));
+                               goto out;
+                       }
+                       /* else fall through for normal semop() */
                case SEMOP:
                        /* struct sembuf is the same on 32 and 64bit :)) */
-                       err = sys_semop (first, (struct sembuf *)AA(ptr), second);
+                       err = sys_semtimedop (first, (struct sembuf *)AA(ptr),
+                                             second, NULL);
                        goto out;
                case SEMGET:
                        err = sys_semget (first, second, third);
index b41f095c1a030d1bb16cfb96cc97c6a10d42715b..51038c69733f6d82cc47a29189ccbadf8737071b 100644 (file)
@@ -184,8 +184,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
  * This is really horribly ugly.
  */
 asmlinkage __SYS_RETTYPE sys_ipc (uint call, int first, int second, 
-                                 unsigned long third, void *ptr,
-                                 unsigned long fifth)
+                                 unsigned long third, void *ptr)
 {
         struct ipc_kludge tmp;
        int ret;
@@ -195,8 +194,8 @@ asmlinkage __SYS_RETTYPE sys_ipc (uint call, int first, int second,
                return sys_semtimedop (first, (struct sembuf *) ptr, second,
                                       NULL);
        case SEMTIMEDOP:
-               return sys_semtimedop(first, (struct sembuf *) ptr, second,
-                                     (const struct timespec *) fifth);
+               return sys_semtimedop (first, (struct sembuf *) ptr, second,
+                                      (const struct timespec *) third);
         case SEMGET:
                 return sys_semget (first, second, third);
         case SEMCTL: {