Skip to content

Commit

Permalink
fuse: 32-bit user space ioctl compat for fuse device
Browse files Browse the repository at this point in the history
With a 64-bit kernel build the FUSE device cannot handle ioctl requests
coming from 32-bit user space.  This is due to the ioctl command
translation that generates different command identifiers that thus cannot
be used for direct comparisons without proper manipulation.

Explicitly extract type and number from the ioctl command to enable 32-bit
user space compatibility on 64-bit kernel builds.

Signed-off-by: Alessio Balsini <balsini@android.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
  • Loading branch information
balsini authored and Miklos Szeredi committed Mar 16, 2021
1 parent 3f9b9ef commit f8425c9
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 11 deletions.
26 changes: 16 additions & 10 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2229,19 +2229,21 @@ static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int err = -ENOTTY;
int res;
int oldfd;
struct fuse_dev *fud = NULL;

if (cmd == FUSE_DEV_IOC_CLONE) {
int oldfd;
if (_IOC_TYPE(cmd) != FUSE_DEV_IOC_MAGIC)
return -ENOTTY;

err = -EFAULT;
if (!get_user(oldfd, (__u32 __user *) arg)) {
switch (_IOC_NR(cmd)) {
case _IOC_NR(FUSE_DEV_IOC_CLONE):
res = -EFAULT;
if (!get_user(oldfd, (__u32 __user *)arg)) {
struct file *old = fget(oldfd);

err = -EINVAL;
res = -EINVAL;
if (old) {
struct fuse_dev *fud = NULL;

/*
* Check against file->f_op because CUSE
* uses the same ioctl handler.
Expand All @@ -2252,14 +2254,18 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd,

if (fud) {
mutex_lock(&fuse_mutex);
err = fuse_device_clone(fud->fc, file);
res = fuse_device_clone(fud->fc, file);
mutex_unlock(&fuse_mutex);
}
fput(old);
}
}
break;
default:
res = -ENOTTY;
break;
}
return err;
return res;
}

const struct file_operations fuse_dev_operations = {
Expand Down
3 changes: 2 additions & 1 deletion include/uapi/linux/fuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,8 @@ struct fuse_notify_retrieve_in {
};

/* Device ioctls: */
#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t)
#define FUSE_DEV_IOC_MAGIC 229
#define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t)

struct fuse_lseek_in {
uint64_t fh;
Expand Down

0 comments on commit f8425c9

Please sign in to comment.