]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - block/compat_ioctl.c
1 #include <linux/blkdev.h>
2 #include <linux/blkpg.h>
3 #include <linux/blktrace_api.h>
4 #include <linux/cdrom.h>
5 #include <linux/compat.h>
6 #include <linux/elevator.h>
8 #include <linux/hdreg.h>
9 #include <linux/syscalls.h>
10 #include <linux/smp_lock.h>
11 #include <linux/types.h>
12 #include <linux/uaccess.h>
14 static int compat_put_ushort(unsigned long arg
, unsigned short val
)
16 return put_user(val
, (unsigned short __user
*)compat_ptr(arg
));
19 static int compat_put_int(unsigned long arg
, int val
)
21 return put_user(val
, (compat_int_t __user
*)compat_ptr(arg
));
24 static int compat_put_long(unsigned long arg
, long val
)
26 return put_user(val
, (compat_long_t __user
*)compat_ptr(arg
));
29 static int compat_put_ulong(unsigned long arg
, compat_ulong_t val
)
31 return put_user(val
, (compat_ulong_t __user
*)compat_ptr(arg
));
34 static int compat_put_u64(unsigned long arg
, u64 val
)
36 return put_user(val
, (compat_u64 __user
*)compat_ptr(arg
));
39 #define BLKBSZGET_32 _IOR(0x12, 112, int)
40 #define BLKBSZSET_32 _IOW(0x12, 113, int)
41 #define BLKGETSIZE64_32 _IOR(0x12, 114, int)
43 static int compat_blkdev_driver_ioctl(struct inode
*inode
, struct file
*file
,
44 struct gendisk
*disk
, unsigned cmd
, unsigned long arg
)
50 * No handler required for the ones below, we just need to
51 * convert arg to a 64 bit pointer.
55 * 0x03 -- HD/IDE ioctl's used by hdparm and friends.
56 * Some need translations, these do not.
58 case HDIO_GET_IDENTITY
:
62 /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
64 /* 0x02 -- Floppy ioctls */
87 case CDROMREADTOCENTRY
:
93 case CDROMMULTISESSION
:
100 case CDROM_DISC_STATUS
:
101 case CDROM_CHANGER_NSLOTS
:
102 case CDROM_GET_CAPABILITY
:
103 /* Ignore cdrom.h about these next 5 ioctls, they absolutely do
104 * not take a struct cdrom_read, instead they take a struct cdrom_msf
105 * which is compatible.
110 case CDROMREADCOOKED
:
113 case DVD_READ_STRUCT
:
114 case DVD_WRITE_STRUCT
:
116 arg
= (unsigned long)compat_ptr(arg
);
117 /* These intepret arg as an unsigned long, not as a pointer,
118 * so we must not do compat_ptr() conversion. */
119 case HDIO_SET_MULTCOUNT
:
120 case HDIO_SET_UNMASKINTR
:
121 case HDIO_SET_KEEPSETTINGS
:
123 case HDIO_SET_NOWERR
:
125 case HDIO_SET_PIO_MODE
:
127 case HDIO_SET_WCACHE
:
128 case HDIO_SET_ACOUSTIC
:
129 case HDIO_SET_BUSSTATE
:
130 case HDIO_SET_ADDRESS
:
132 case CDROM_SET_OPTIONS
:
133 case CDROM_CLEAR_OPTIONS
:
134 case CDROM_SELECT_SPEED
:
135 case CDROM_SELECT_DISC
:
136 case CDROM_MEDIA_CHANGED
:
137 case CDROM_DRIVE_STATUS
:
142 /* unknown ioctl number */
146 if (disk
->fops
->unlocked_ioctl
)
147 return disk
->fops
->unlocked_ioctl(file
, cmd
, arg
);
149 if (disk
->fops
->ioctl
) {
151 ret
= disk
->fops
->ioctl(inode
, file
, cmd
, arg
);
159 static int compat_blkdev_locked_ioctl(struct inode
*inode
, struct file
*file
,
160 struct block_device
*bdev
,
161 unsigned cmd
, unsigned long arg
)
163 struct backing_dev_info
*bdi
;
170 bdi
= blk_get_backing_dev_info(bdev
);
173 return compat_put_long(arg
,
174 (bdi
->ra_pages
* PAGE_CACHE_SIZE
) / 512);
175 case BLKROGET
: /* compatible */
176 return compat_put_int(arg
, bdev_read_only(bdev
) != 0);
177 case BLKBSZGET_32
: /* get the logical block size (cf. BLKSSZGET) */
178 return compat_put_int(arg
, block_size(bdev
));
179 case BLKSSZGET
: /* get block device hardware sector size */
180 return compat_put_int(arg
, bdev_hardsect_size(bdev
));
182 return compat_put_ushort(arg
,
183 bdev_get_queue(bdev
)->max_sectors
);
184 case BLKRASET
: /* compatible, but no compat_ptr (!) */
186 if (!capable(CAP_SYS_ADMIN
))
188 bdi
= blk_get_backing_dev_info(bdev
);
191 bdi
->ra_pages
= (arg
* 512) / PAGE_CACHE_SIZE
;
194 if ((bdev
->bd_inode
->i_size
>> 9) > ~0UL)
196 return compat_put_ulong(arg
, bdev
->bd_inode
->i_size
>> 9);
198 case BLKGETSIZE64_32
:
199 return compat_put_u64(arg
, bdev
->bd_inode
->i_size
);
204 /* Most of the generic ioctls are handled in the normal fallback path.
205 This assumes the blkdev's low level compat_ioctl always returns
206 ENOIOCTLCMD for unknown ioctls. */
207 long compat_blkdev_ioctl(struct file
*file
, unsigned cmd
, unsigned long arg
)
209 int ret
= -ENOIOCTLCMD
;
210 struct inode
*inode
= file
->f_mapping
->host
;
211 struct block_device
*bdev
= inode
->i_bdev
;
212 struct gendisk
*disk
= bdev
->bd_disk
;
218 * the ones below are implemented in blkdev_locked_ioctl,
219 * but we call blkdev_ioctl, which gets the lock for us
222 return blkdev_ioctl(inode
, file
, cmd
,
223 (unsigned long)compat_ptr(arg
));
225 return blkdev_ioctl(inode
, file
, BLKBSZSET
,
226 (unsigned long)compat_ptr(arg
));
230 ret
= compat_blkdev_locked_ioctl(inode
, file
, bdev
, cmd
, arg
);
231 /* FIXME: why do we assume -> compat_ioctl needs the BKL? */
232 if (ret
== -ENOIOCTLCMD
&& disk
->fops
->compat_ioctl
)
233 ret
= disk
->fops
->compat_ioctl(file
, cmd
, arg
);
236 if (ret
!= -ENOIOCTLCMD
)
239 return compat_blkdev_driver_ioctl(inode
, file
, disk
, cmd
, arg
);