1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/blkdev.h>
3 #include <linux/blkpg.h>
4 #include <linux/blktrace_api.h>
5 #include <linux/cdrom.h>
6 #include <linux/compat.h>
7 #include <linux/elevator.h>
8 #include <linux/hdreg.h>
9 #include <linux/slab.h>
10 #include <linux/syscalls.h>
11 #include <linux/types.h>
12 #include <linux/uaccess.h>
13 
compat_put_ushort(unsigned long arg,unsigned short val)14 static int compat_put_ushort(unsigned long arg, unsigned short val)
15 {
16 	return put_user(val, (unsigned short __user *)compat_ptr(arg));
17 }
18 
compat_put_int(unsigned long arg,int val)19 static int compat_put_int(unsigned long arg, int val)
20 {
21 	return put_user(val, (compat_int_t __user *)compat_ptr(arg));
22 }
23 
compat_put_uint(unsigned long arg,unsigned int val)24 static int compat_put_uint(unsigned long arg, unsigned int val)
25 {
26 	return put_user(val, (compat_uint_t __user *)compat_ptr(arg));
27 }
28 
compat_put_long(unsigned long arg,long val)29 static int compat_put_long(unsigned long arg, long val)
30 {
31 	return put_user(val, (compat_long_t __user *)compat_ptr(arg));
32 }
33 
compat_put_ulong(unsigned long arg,compat_ulong_t val)34 static int compat_put_ulong(unsigned long arg, compat_ulong_t val)
35 {
36 	return put_user(val, (compat_ulong_t __user *)compat_ptr(arg));
37 }
38 
compat_put_u64(unsigned long arg,u64 val)39 static int compat_put_u64(unsigned long arg, u64 val)
40 {
41 	return put_user(val, (compat_u64 __user *)compat_ptr(arg));
42 }
43 
44 struct compat_hd_geometry {
45 	unsigned char heads;
46 	unsigned char sectors;
47 	unsigned short cylinders;
48 	u32 start;
49 };
50 
compat_hdio_getgeo(struct gendisk * disk,struct block_device * bdev,struct compat_hd_geometry __user * ugeo)51 static int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev,
52 			struct compat_hd_geometry __user *ugeo)
53 {
54 	struct hd_geometry geo;
55 	int ret;
56 
57 	if (!ugeo)
58 		return -EINVAL;
59 	if (!disk->fops->getgeo)
60 		return -ENOTTY;
61 
62 	memset(&geo, 0, sizeof(geo));
63 	/*
64 	 * We need to set the startsect first, the driver may
65 	 * want to override it.
66 	 */
67 	geo.start = get_start_sect(bdev);
68 	ret = disk->fops->getgeo(bdev, &geo);
69 	if (ret)
70 		return ret;
71 
72 	ret = copy_to_user(ugeo, &geo, 4);
73 	ret |= put_user(geo.start, &ugeo->start);
74 	if (ret)
75 		ret = -EFAULT;
76 
77 	return ret;
78 }
79 
compat_hdio_ioctl(struct block_device * bdev,fmode_t mode,unsigned int cmd,unsigned long arg)80 static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
81 		unsigned int cmd, unsigned long arg)
82 {
83 	unsigned long __user *p;
84 	int error;
85 
86 	p = compat_alloc_user_space(sizeof(unsigned long));
87 	error = __blkdev_driver_ioctl(bdev, mode,
88 				cmd, (unsigned long)p);
89 	if (error == 0) {
90 		unsigned int __user *uvp = compat_ptr(arg);
91 		unsigned long v;
92 		if (get_user(v, p) || put_user(v, uvp))
93 			error = -EFAULT;
94 	}
95 	return error;
96 }
97 
98 struct compat_cdrom_read_audio {
99 	union cdrom_addr	addr;
100 	u8			addr_format;
101 	compat_int_t		nframes;
102 	compat_caddr_t		buf;
103 };
104 
105 struct compat_cdrom_generic_command {
106 	unsigned char	cmd[CDROM_PACKET_SIZE];
107 	compat_caddr_t	buffer;
108 	compat_uint_t	buflen;
109 	compat_int_t	stat;
110 	compat_caddr_t	sense;
111 	unsigned char	data_direction;
112 	compat_int_t	quiet;
113 	compat_int_t	timeout;
114 	compat_caddr_t	reserved[1];
115 };
116 
compat_cdrom_read_audio(struct block_device * bdev,fmode_t mode,unsigned int cmd,unsigned long arg)117 static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
118 		unsigned int cmd, unsigned long arg)
119 {
120 	struct cdrom_read_audio __user *cdread_audio;
121 	struct compat_cdrom_read_audio __user *cdread_audio32;
122 	__u32 data;
123 	void __user *datap;
124 
125 	cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
126 	cdread_audio32 = compat_ptr(arg);
127 
128 	if (copy_in_user(&cdread_audio->addr,
129 			 &cdread_audio32->addr,
130 			 (sizeof(*cdread_audio32) -
131 			  sizeof(compat_caddr_t))))
132 		return -EFAULT;
133 
134 	if (get_user(data, &cdread_audio32->buf))
135 		return -EFAULT;
136 	datap = compat_ptr(data);
137 	if (put_user(datap, &cdread_audio->buf))
138 		return -EFAULT;
139 
140 	return __blkdev_driver_ioctl(bdev, mode, cmd,
141 			(unsigned long)cdread_audio);
142 }
143 
compat_cdrom_generic_command(struct block_device * bdev,fmode_t mode,unsigned int cmd,unsigned long arg)144 static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
145 		unsigned int cmd, unsigned long arg)
146 {
147 	struct cdrom_generic_command __user *cgc;
148 	struct compat_cdrom_generic_command __user *cgc32;
149 	u32 data;
150 	unsigned char dir;
151 	int itmp;
152 
153 	cgc = compat_alloc_user_space(sizeof(*cgc));
154 	cgc32 = compat_ptr(arg);
155 
156 	if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
157 	    get_user(data, &cgc32->buffer) ||
158 	    put_user(compat_ptr(data), &cgc->buffer) ||
159 	    copy_in_user(&cgc->buflen, &cgc32->buflen,
160 			 (sizeof(unsigned int) + sizeof(int))) ||
161 	    get_user(data, &cgc32->sense) ||
162 	    put_user(compat_ptr(data), &cgc->sense) ||
163 	    get_user(dir, &cgc32->data_direction) ||
164 	    put_user(dir, &cgc->data_direction) ||
165 	    get_user(itmp, &cgc32->quiet) ||
166 	    put_user(itmp, &cgc->quiet) ||
167 	    get_user(itmp, &cgc32->timeout) ||
168 	    put_user(itmp, &cgc->timeout) ||
169 	    get_user(data, &cgc32->reserved[0]) ||
170 	    put_user(compat_ptr(data), &cgc->reserved[0]))
171 		return -EFAULT;
172 
173 	return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
174 }
175 
176 struct compat_blkpg_ioctl_arg {
177 	compat_int_t op;
178 	compat_int_t flags;
179 	compat_int_t datalen;
180 	compat_caddr_t data;
181 };
182 
compat_blkpg_ioctl(struct block_device * bdev,fmode_t mode,unsigned int cmd,struct compat_blkpg_ioctl_arg __user * ua32)183 static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
184 		unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
185 {
186 	struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
187 	compat_caddr_t udata;
188 	compat_int_t n;
189 	int err;
190 
191 	err = get_user(n, &ua32->op);
192 	err |= put_user(n, &a->op);
193 	err |= get_user(n, &ua32->flags);
194 	err |= put_user(n, &a->flags);
195 	err |= get_user(n, &ua32->datalen);
196 	err |= put_user(n, &a->datalen);
197 	err |= get_user(udata, &ua32->data);
198 	err |= put_user(compat_ptr(udata), &a->data);
199 	if (err)
200 		return err;
201 
202 	return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
203 }
204 
205 #define BLKBSZGET_32		_IOR(0x12, 112, int)
206 #define BLKBSZSET_32		_IOW(0x12, 113, int)
207 #define BLKGETSIZE64_32		_IOR(0x12, 114, int)
208 
compat_blkdev_driver_ioctl(struct block_device * bdev,fmode_t mode,unsigned cmd,unsigned long arg)209 static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
210 			unsigned cmd, unsigned long arg)
211 {
212 	switch (cmd) {
213 	case HDIO_GET_UNMASKINTR:
214 	case HDIO_GET_MULTCOUNT:
215 	case HDIO_GET_KEEPSETTINGS:
216 	case HDIO_GET_32BIT:
217 	case HDIO_GET_NOWERR:
218 	case HDIO_GET_DMA:
219 	case HDIO_GET_NICE:
220 	case HDIO_GET_WCACHE:
221 	case HDIO_GET_ACOUSTIC:
222 	case HDIO_GET_ADDRESS:
223 	case HDIO_GET_BUSSTATE:
224 		return compat_hdio_ioctl(bdev, mode, cmd, arg);
225 	case CDROMREADAUDIO:
226 		return compat_cdrom_read_audio(bdev, mode, cmd, arg);
227 	case CDROM_SEND_PACKET:
228 		return compat_cdrom_generic_command(bdev, mode, cmd, arg);
229 
230 	/*
231 	 * No handler required for the ones below, we just need to
232 	 * convert arg to a 64 bit pointer.
233 	 */
234 	case BLKSECTSET:
235 	/*
236 	 * 0x03 -- HD/IDE ioctl's used by hdparm and friends.
237 	 *         Some need translations, these do not.
238 	 */
239 	case HDIO_GET_IDENTITY:
240 	case HDIO_DRIVE_TASK:
241 	case HDIO_DRIVE_CMD:
242 	/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
243 	case 0x330:
244 	/* CDROM stuff */
245 	case CDROMPAUSE:
246 	case CDROMRESUME:
247 	case CDROMPLAYMSF:
248 	case CDROMPLAYTRKIND:
249 	case CDROMREADTOCHDR:
250 	case CDROMREADTOCENTRY:
251 	case CDROMSTOP:
252 	case CDROMSTART:
253 	case CDROMEJECT:
254 	case CDROMVOLCTRL:
255 	case CDROMSUBCHNL:
256 	case CDROMMULTISESSION:
257 	case CDROM_GET_MCN:
258 	case CDROMRESET:
259 	case CDROMVOLREAD:
260 	case CDROMSEEK:
261 	case CDROMPLAYBLK:
262 	case CDROMCLOSETRAY:
263 	case CDROM_DISC_STATUS:
264 	case CDROM_CHANGER_NSLOTS:
265 	case CDROM_GET_CAPABILITY:
266 	/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
267 	 * not take a struct cdrom_read, instead they take a struct cdrom_msf
268 	 * which is compatible.
269 	 */
270 	case CDROMREADMODE2:
271 	case CDROMREADMODE1:
272 	case CDROMREADRAW:
273 	case CDROMREADCOOKED:
274 	case CDROMREADALL:
275 	/* DVD ioctls */
276 	case DVD_READ_STRUCT:
277 	case DVD_WRITE_STRUCT:
278 	case DVD_AUTH:
279 		arg = (unsigned long)compat_ptr(arg);
280 	/* These intepret arg as an unsigned long, not as a pointer,
281 	 * so we must not do compat_ptr() conversion. */
282 	case HDIO_SET_MULTCOUNT:
283 	case HDIO_SET_UNMASKINTR:
284 	case HDIO_SET_KEEPSETTINGS:
285 	case HDIO_SET_32BIT:
286 	case HDIO_SET_NOWERR:
287 	case HDIO_SET_DMA:
288 	case HDIO_SET_PIO_MODE:
289 	case HDIO_SET_NICE:
290 	case HDIO_SET_WCACHE:
291 	case HDIO_SET_ACOUSTIC:
292 	case HDIO_SET_BUSSTATE:
293 	case HDIO_SET_ADDRESS:
294 	case CDROMEJECT_SW:
295 	case CDROM_SET_OPTIONS:
296 	case CDROM_CLEAR_OPTIONS:
297 	case CDROM_SELECT_SPEED:
298 	case CDROM_SELECT_DISC:
299 	case CDROM_MEDIA_CHANGED:
300 	case CDROM_DRIVE_STATUS:
301 	case CDROM_LOCKDOOR:
302 	case CDROM_DEBUG:
303 		break;
304 	default:
305 		/* unknown ioctl number */
306 		return -ENOIOCTLCMD;
307 	}
308 
309 	return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
310 }
311 
312 /* Most of the generic ioctls are handled in the normal fallback path.
313    This assumes the blkdev's low level compat_ioctl always returns
314    ENOIOCTLCMD for unknown ioctls. */
compat_blkdev_ioctl(struct file * file,unsigned cmd,unsigned long arg)315 long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
316 {
317 	int ret = -ENOIOCTLCMD;
318 	struct inode *inode = file->f_mapping->host;
319 	struct block_device *bdev = inode->i_bdev;
320 	struct gendisk *disk = bdev->bd_disk;
321 	fmode_t mode = file->f_mode;
322 	loff_t size;
323 	unsigned int max_sectors;
324 
325 	/*
326 	 * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
327 	 * to updated it before every ioctl.
328 	 */
329 	if (file->f_flags & O_NDELAY)
330 		mode |= FMODE_NDELAY;
331 	else
332 		mode &= ~FMODE_NDELAY;
333 
334 	switch (cmd) {
335 	case HDIO_GETGEO:
336 		return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
337 	case BLKPBSZGET:
338 		return compat_put_uint(arg, bdev_physical_block_size(bdev));
339 	case BLKIOMIN:
340 		return compat_put_uint(arg, bdev_io_min(bdev));
341 	case BLKIOOPT:
342 		return compat_put_uint(arg, bdev_io_opt(bdev));
343 	case BLKALIGNOFF:
344 		return compat_put_int(arg, bdev_alignment_offset(bdev));
345 	case BLKDISCARDZEROES:
346 		return compat_put_uint(arg, 0);
347 	case BLKFLSBUF:
348 	case BLKROSET:
349 	case BLKDISCARD:
350 	case BLKSECDISCARD:
351 	case BLKZEROOUT:
352 	/*
353 	 * the ones below are implemented in blkdev_locked_ioctl,
354 	 * but we call blkdev_ioctl, which gets the lock for us
355 	 */
356 	case BLKRRPART:
357 		return blkdev_ioctl(bdev, mode, cmd,
358 				(unsigned long)compat_ptr(arg));
359 	case BLKBSZSET_32:
360 		return blkdev_ioctl(bdev, mode, BLKBSZSET,
361 				(unsigned long)compat_ptr(arg));
362 	case BLKPG:
363 		return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
364 	case BLKRAGET:
365 	case BLKFRAGET:
366 		if (!arg)
367 			return -EINVAL;
368 		return compat_put_long(arg,
369 			       (bdev->bd_bdi->ra_pages * PAGE_SIZE) / 512);
370 	case BLKROGET: /* compatible */
371 		return compat_put_int(arg, bdev_read_only(bdev) != 0);
372 	case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
373 		return compat_put_int(arg, block_size(bdev));
374 	case BLKSSZGET: /* get block device hardware sector size */
375 		return compat_put_int(arg, bdev_logical_block_size(bdev));
376 	case BLKSECTGET:
377 		max_sectors = min_t(unsigned int, USHRT_MAX,
378 				    queue_max_sectors(bdev_get_queue(bdev)));
379 		return compat_put_ushort(arg, max_sectors);
380 	case BLKROTATIONAL:
381 		return compat_put_ushort(arg,
382 					 !blk_queue_nonrot(bdev_get_queue(bdev)));
383 	case BLKRASET: /* compatible, but no compat_ptr (!) */
384 	case BLKFRASET:
385 		if (!capable(CAP_SYS_ADMIN))
386 			return -EACCES;
387 		bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE;
388 		return 0;
389 	case BLKGETSIZE:
390 		size = i_size_read(bdev->bd_inode);
391 		if ((size >> 9) > ~0UL)
392 			return -EFBIG;
393 		return compat_put_ulong(arg, size >> 9);
394 
395 	case BLKGETSIZE64_32:
396 		return compat_put_u64(arg, i_size_read(bdev->bd_inode));
397 
398 	case BLKTRACESETUP32:
399 	case BLKTRACESTART: /* compatible */
400 	case BLKTRACESTOP:  /* compatible */
401 	case BLKTRACETEARDOWN: /* compatible */
402 		ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
403 		return ret;
404 	default:
405 		if (disk->fops->compat_ioctl)
406 			ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
407 		if (ret == -ENOIOCTLCMD)
408 			ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
409 		return ret;
410 	}
411 }
412