static long do_locks(unsigned int fd, unsigned int cmd, unsigned long 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; }
asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) { struct oabi_flock64 user; struct flock64 kernel; mm_segment_t fs = USER_DS; /* initialized to kill a warning */ unsigned long local_arg = arg; int ret; switch (cmd) { case F_GETLKP: case F_SETLKP: case F_SETLKPW: case F_GETLK64: case F_SETLK64: case F_SETLKW64: 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; local_arg = (unsigned long)&kernel; fs = get_fs(); set_fs(KERNEL_DS); } ret = sys_fcntl64(fd, cmd, local_arg); switch (cmd) { case F_GETLK64: if (!ret) { 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; } case F_SETLK64: case F_SETLKW64: set_fs(fs); } return ret; }
asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) { switch (cmd) { case F_OFD_GETLK: case F_OFD_SETLK: case F_OFD_SETLKW: case F_GETLK64: case F_SETLK64: case F_SETLKW64: return do_locks(fd, cmd, arg); default: return sys_fcntl64(fd, cmd, arg); } }
/** Handler for doing an FCNTL64 in a FAF open file. * @author Renaud Lottiaux * * @param from Node sending the request * @param msgIn Request message */ void handle_faf_fcntl64 (struct rpc_desc* desc, void *msgIn, size_t size) { struct faf_ctl_msg *msg = msgIn; const struct cred *old_cred; unsigned long arg; long r; int err; if (msg->cmd == F_GETLK64 || msg->cmd == F_SETLK64 || msg->cmd == F_SETLKW64) arg = (unsigned long) &msg->flock64; else arg = msg->arg; old_cred = unpack_override_creds(desc); if (IS_ERR(old_cred)) goto cancel; err = remote_sleep_prepare(desc); if (err) { revert_creds(old_cred); goto cancel; } r = sys_fcntl64 (msg->server_fd, msg->cmd, arg); remote_sleep_finish(); revert_creds(old_cred); err = rpc_pack_type(desc, r); if (unlikely(err)) goto cancel; if (!r && msg->cmd == F_GETLK64) { err = rpc_pack_type(desc, msg->flock64); if (unlikely(err)) goto cancel; } return; cancel: rpc_cancel(desc); }