^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/drivers/char/raw.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Front-end raw character devices. These can be bound to any block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * devices to provide genuine Unix raw character device semantics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * We reserve minor number 0 for a control interface. ioctl()s on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * device are used to bind the other minor numbers to block devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/backing-dev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/raw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/capability.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/uio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/cdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct raw_device_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) dev_t binding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct block_device *bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int inuse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static struct class *raw_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static struct raw_device_data *raw_devices;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static DEFINE_MUTEX(raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static const struct file_operations raw_ctl_fops; /* forward declaration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static int max_raw_minors = CONFIG_MAX_RAW_DEVS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) module_param(max_raw_minors, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_PARM_DESC(max_raw_minors, "Maximum number of raw devices (1-65536)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Open/close code for raw IO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * We just rewrite the i_mapping for the /dev/raw/rawN file descriptor to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * point at the blockdev's address_space and set the file handle to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * O_DIRECT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Set the device's soft blocksize to the minimum possible. This gives the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * finest possible alignment and has no adverse impact on performance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static int raw_open(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const int minor = iminor(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct block_device *bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (minor == 0) { /* It is the control device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) filp->f_op = &raw_ctl_fops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) pr_warn_ratelimited(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) "process %s (pid %d) is using the deprecated raw device\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) "support will be removed in Linux 5.14.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) current->comm, current->pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) mutex_lock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * All we need to do on open is check that the device is bound.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!raw_devices[minor].binding)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) bdev = blkdev_get_by_dev(raw_devices[minor].binding,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) filp->f_mode | FMODE_EXCL, raw_open);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (IS_ERR(bdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) err = PTR_ERR(bdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) err = set_blocksize(bdev, bdev_logical_block_size(bdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) goto out1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) filp->f_flags |= O_DIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) filp->f_mapping = bdev->bd_inode->i_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (++raw_devices[minor].inuse == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) file_inode(filp)->i_mapping =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) bdev->bd_inode->i_mapping;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) filp->private_data = bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) raw_devices[minor].bdev = bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) mutex_unlock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) out1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) mutex_unlock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * When the final fd which refers to this character-special node is closed, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * make its ->mapping point back at its own i_data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int raw_release(struct inode *inode, struct file *filp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) const int minor= iminor(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct block_device *bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mutex_lock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) bdev = raw_devices[minor].bdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (--raw_devices[minor].inuse == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Here inode->i_mapping == bdev->bd_inode->i_mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) inode->i_mapping = &inode->i_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) mutex_unlock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) blkdev_put(bdev, filp->f_mode | FMODE_EXCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * Forward ioctls to the underlying block device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) raw_ioctl(struct file *filp, unsigned int command, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct block_device *bdev = filp->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return blkdev_ioctl(bdev, 0, command, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int bind_set(int number, u64 major, u64 minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dev_t dev = MKDEV(major, minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) dev_t raw = MKDEV(RAW_MAJOR, number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct raw_device_data *rawdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (number <= 0 || number >= max_raw_minors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (MAJOR(dev) != major || MINOR(dev) != minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) rawdev = &raw_devices[number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * This is like making block devices, so demand the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * same capability
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!capable(CAP_SYS_ADMIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * For now, we don't need to check that the underlying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * block device is present or not: we can do that when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * the raw device is opened. Just check that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * major/minor numbers make sense.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (MAJOR(dev) == 0 && dev != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mutex_lock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (rawdev->inuse) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mutex_unlock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (rawdev->binding)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) module_put(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) rawdev->binding = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* unbind */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) device_destroy(raw_class, raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) __module_get(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) device_destroy(raw_class, raw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) device_create(raw_class, NULL, raw, NULL, "raw%d", number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) mutex_unlock(&raw_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int bind_get(int number, dev_t *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (number <= 0 || number >= max_raw_minors)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *dev = raw_devices[number].binding;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * Deal with ioctls against the raw-device control interface, to bind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * and unbind other raw devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static long raw_ctl_ioctl(struct file *filp, unsigned int command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) struct raw_config_request rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dev_t dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) switch (command) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case RAW_SETBIND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case RAW_GETBIND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) err = bind_get(rq.raw_minor, &dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) rq.block_major = MAJOR(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) rq.block_minor = MINOR(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (copy_to_user((void __user *)arg, &rq, sizeof(rq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct raw32_config_request {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) compat_int_t raw_minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) compat_u64 block_major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) compat_u64 block_minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct raw32_config_request __user *user_req = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct raw32_config_request rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) dev_t dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) case RAW_SETBIND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (copy_from_user(&rq, user_req, sizeof(rq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case RAW_GETBIND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (copy_from_user(&rq, user_req, sizeof(rq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) err = bind_get(rq.raw_minor, &dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) rq.block_major = MAJOR(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) rq.block_minor = MINOR(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (copy_to_user(user_req, &rq, sizeof(rq)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static const struct file_operations raw_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .read_iter = blkdev_read_iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .write_iter = blkdev_write_iter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .fsync = blkdev_fsync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .open = raw_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .release = raw_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .unlocked_ioctl = raw_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static const struct file_operations raw_ctl_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .unlocked_ioctl = raw_ctl_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .compat_ioctl = raw_ctl_compat_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .open = raw_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .llseek = noop_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static struct cdev raw_cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static char *raw_devnode(struct device *dev, umode_t *mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return kasprintf(GFP_KERNEL, "raw/%s", dev_name(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int __init raw_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dev_t dev = MKDEV(RAW_MAJOR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (max_raw_minors < 1 || max_raw_minors > 65536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) pr_warn("raw: invalid max_raw_minors (must be between 1 and 65536), using %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) CONFIG_MAX_RAW_DEVS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) max_raw_minors = CONFIG_MAX_RAW_DEVS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) raw_devices = vzalloc(array_size(max_raw_minors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) sizeof(struct raw_device_data)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (!raw_devices) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) printk(KERN_ERR "Not enough memory for raw device structures\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ret = register_chrdev_region(dev, max_raw_minors, "raw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) cdev_init(&raw_cdev, &raw_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret = cdev_add(&raw_cdev, dev, max_raw_minors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) goto error_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) raw_class = class_create(THIS_MODULE, "raw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (IS_ERR(raw_class)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) printk(KERN_ERR "Error creating raw class.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) cdev_del(&raw_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret = PTR_ERR(raw_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto error_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) raw_class->devnode = raw_devnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) error_region:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) unregister_chrdev_region(dev, max_raw_minors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) vfree(raw_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static void __exit raw_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) class_destroy(raw_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) cdev_del(&raw_cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), max_raw_minors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) module_init(raw_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) module_exit(raw_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) MODULE_LICENSE("GPL");