ARM: 9111/1: oabi-compat: rework fcntl64() emulation
authorArnd Bergmann <arnd@arndb.de>
Wed, 11 Aug 2021 07:30:24 +0000 (08:30 +0100)
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Fri, 20 Aug 2021 10:39:27 +0000 (11:39 +0100)
This is one of the last users of get_fs(), and this is fairly easy to
change, since the infrastructure for it is already there.

The replacement here is essentially a copy of the existing fcntl64()
syscall entry function.

Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
arch/arm/kernel/sys_oabi-compat.c

index 5ea365c..223ee46 100644 (file)
@@ -194,56 +194,83 @@ struct oabi_flock64 {
        pid_t   l_pid;
 } __attribute__ ((packed,aligned(4)));
 
-static long do_locks(unsigned int fd, unsigned int cmd,
-                                unsigned long arg)
+static int get_oabi_flock(struct flock64 *kernel, struct oabi_flock64 __user *arg)
 {
-       struct flock64 kernel;
        struct oabi_flock64 user;
-       mm_segment_t fs;
-       long ret;
 
        if (copy_from_user(&user, (struct oabi_flock64 __user *)arg,
                           sizeof(user)))
                return -EFAULT;
-       kernel.l_type   = user.l_type;
-       kernel.l_whence = user.l_whence;
-       kernel.l_start  = user.l_start;
-       kernel.l_len    = user.l_len;
-       kernel.l_pid    = user.l_pid;
-
-       fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = sys_fcntl64(fd, cmd, (unsigned long)&kernel);
-       set_fs(fs);
-
-       if (!ret && (cmd == F_GETLK64 || cmd == F_OFD_GETLK)) {
-               user.l_type     = kernel.l_type;
-               user.l_whence   = kernel.l_whence;
-               user.l_start    = kernel.l_start;
-               user.l_len      = kernel.l_len;
-               user.l_pid      = kernel.l_pid;
-               if (copy_to_user((struct oabi_flock64 __user *)arg,
-                                &user, sizeof(user)))
-                       ret = -EFAULT;
-       }
-       return ret;
+
+       kernel->l_type   = user.l_type;
+       kernel->l_whence = user.l_whence;
+       kernel->l_start  = user.l_start;
+       kernel->l_len    = user.l_len;
+       kernel->l_pid    = user.l_pid;
+
+       return 0;
+}
+
+static int put_oabi_flock(struct flock64 *kernel, struct oabi_flock64 __user *arg)
+{
+       struct oabi_flock64 user;
+
+       user.l_type     = kernel->l_type;
+       user.l_whence   = kernel->l_whence;
+       user.l_start    = kernel->l_start;
+       user.l_len      = kernel->l_len;
+       user.l_pid      = kernel->l_pid;
+
+       if (copy_to_user((struct oabi_flock64 __user *)arg,
+                        &user, sizeof(user)))
+               return -EFAULT;
+
+       return 0;
 }
 
 asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
                                 unsigned long arg)
 {
+       void __user *argp = (void __user *)arg;
+       struct fd f = fdget_raw(fd);
+       struct flock64 flock;
+       long err = -EBADF;
+
+       if (!f.file)
+               goto out;
+
        switch (cmd) {
-       case F_OFD_GETLK:
-       case F_OFD_SETLK:
-       case F_OFD_SETLKW:
        case F_GETLK64:
+       case F_OFD_GETLK:
+               err = security_file_fcntl(f.file, cmd, arg);
+               if (err)
+                       break;
+               err = get_oabi_flock(&flock, argp);
+               if (err)
+                       break;
+               err = fcntl_getlk64(f.file, cmd, &flock);
+               if (!err)
+                      err = put_oabi_flock(&flock, argp);
+               break;
        case F_SETLK64:
        case F_SETLKW64:
-               return do_locks(fd, cmd, arg);
-
+       case F_OFD_SETLK:
+       case F_OFD_SETLKW:
+               err = security_file_fcntl(f.file, cmd, arg);
+               if (err)
+                       break;
+               err = get_oabi_flock(&flock, argp);
+               if (err)
+                       break;
+               err = fcntl_setlk64(fd, f.file, cmd, &flock);
+               break;
        default:
-               return sys_fcntl64(fd, cmd, arg);
+               err = sys_fcntl64(fd, cmd, arg);
+               break;
        }
+       fdput(f);
+out:
+       return err;
 }
 
 struct oabi_epoll_event {