Linux Audio

Check our new training course

Loading...
v3.1
 
  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>
  7#include <linux/fd.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
 14static int compat_put_ushort(unsigned long arg, unsigned short val)
 15{
 16	return put_user(val, (unsigned short __user *)compat_ptr(arg));
 17}
 18
 19static int compat_put_int(unsigned long arg, int val)
 20{
 21	return put_user(val, (compat_int_t __user *)compat_ptr(arg));
 22}
 23
 24static 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
 29static int compat_put_long(unsigned long arg, long val)
 30{
 31	return put_user(val, (compat_long_t __user *)compat_ptr(arg));
 32}
 33
 34static 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
 39static int compat_put_u64(unsigned long arg, u64 val)
 40{
 41	return put_user(val, (compat_u64 __user *)compat_ptr(arg));
 42}
 43
 44struct compat_hd_geometry {
 45	unsigned char heads;
 46	unsigned char sectors;
 47	unsigned short cylinders;
 48	u32 start;
 49};
 50
 51static 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	/*
 63	 * We need to set the startsect first, the driver may
 64	 * want to override it.
 65	 */
 66	geo.start = get_start_sect(bdev);
 67	ret = disk->fops->getgeo(bdev, &geo);
 68	if (ret)
 69		return ret;
 70
 71	ret = copy_to_user(ugeo, &geo, 4);
 72	ret |= __put_user(geo.start, &ugeo->start);
 73	if (ret)
 74		ret = -EFAULT;
 75
 76	return ret;
 77}
 78
 79static int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode,
 80		unsigned int cmd, unsigned long arg)
 81{
 82	mm_segment_t old_fs = get_fs();
 83	unsigned long kval;
 84	unsigned int __user *uvp;
 85	int error;
 86
 87	set_fs(KERNEL_DS);
 88	error = __blkdev_driver_ioctl(bdev, mode,
 89				cmd, (unsigned long)(&kval));
 90	set_fs(old_fs);
 91
 92	if (error == 0) {
 93		uvp = compat_ptr(arg);
 94		if (put_user(kval, uvp))
 
 95			error = -EFAULT;
 96	}
 97	return error;
 98}
 99
100struct compat_cdrom_read_audio {
101	union cdrom_addr	addr;
102	u8			addr_format;
103	compat_int_t		nframes;
104	compat_caddr_t		buf;
105};
106
107struct compat_cdrom_generic_command {
108	unsigned char	cmd[CDROM_PACKET_SIZE];
109	compat_caddr_t	buffer;
110	compat_uint_t	buflen;
111	compat_int_t	stat;
112	compat_caddr_t	sense;
113	unsigned char	data_direction;
114	compat_int_t	quiet;
115	compat_int_t	timeout;
116	compat_caddr_t	reserved[1];
117};
118
119static int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode,
120		unsigned int cmd, unsigned long arg)
121{
122	struct cdrom_read_audio __user *cdread_audio;
123	struct compat_cdrom_read_audio __user *cdread_audio32;
124	__u32 data;
125	void __user *datap;
126
127	cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio));
128	cdread_audio32 = compat_ptr(arg);
129
130	if (copy_in_user(&cdread_audio->addr,
131			 &cdread_audio32->addr,
132			 (sizeof(*cdread_audio32) -
133			  sizeof(compat_caddr_t))))
134		return -EFAULT;
135
136	if (get_user(data, &cdread_audio32->buf))
137		return -EFAULT;
138	datap = compat_ptr(data);
139	if (put_user(datap, &cdread_audio->buf))
140		return -EFAULT;
141
142	return __blkdev_driver_ioctl(bdev, mode, cmd,
143			(unsigned long)cdread_audio);
144}
145
146static int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode,
147		unsigned int cmd, unsigned long arg)
148{
149	struct cdrom_generic_command __user *cgc;
150	struct compat_cdrom_generic_command __user *cgc32;
151	u32 data;
152	unsigned char dir;
153	int itmp;
154
155	cgc = compat_alloc_user_space(sizeof(*cgc));
156	cgc32 = compat_ptr(arg);
157
158	if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
159	    get_user(data, &cgc32->buffer) ||
160	    put_user(compat_ptr(data), &cgc->buffer) ||
161	    copy_in_user(&cgc->buflen, &cgc32->buflen,
162			 (sizeof(unsigned int) + sizeof(int))) ||
163	    get_user(data, &cgc32->sense) ||
164	    put_user(compat_ptr(data), &cgc->sense) ||
165	    get_user(dir, &cgc32->data_direction) ||
166	    put_user(dir, &cgc->data_direction) ||
167	    get_user(itmp, &cgc32->quiet) ||
168	    put_user(itmp, &cgc->quiet) ||
169	    get_user(itmp, &cgc32->timeout) ||
170	    put_user(itmp, &cgc->timeout) ||
171	    get_user(data, &cgc32->reserved[0]) ||
172	    put_user(compat_ptr(data), &cgc->reserved[0]))
173		return -EFAULT;
174
175	return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc);
176}
177
178struct compat_blkpg_ioctl_arg {
179	compat_int_t op;
180	compat_int_t flags;
181	compat_int_t datalen;
182	compat_caddr_t data;
183};
184
185static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode,
186		unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32)
187{
188	struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a));
189	compat_caddr_t udata;
190	compat_int_t n;
191	int err;
192
193	err = get_user(n, &ua32->op);
194	err |= put_user(n, &a->op);
195	err |= get_user(n, &ua32->flags);
196	err |= put_user(n, &a->flags);
197	err |= get_user(n, &ua32->datalen);
198	err |= put_user(n, &a->datalen);
199	err |= get_user(udata, &ua32->data);
200	err |= put_user(compat_ptr(udata), &a->data);
201	if (err)
202		return err;
203
204	return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a);
205}
206
207#define BLKBSZGET_32		_IOR(0x12, 112, int)
208#define BLKBSZSET_32		_IOW(0x12, 113, int)
209#define BLKGETSIZE64_32		_IOR(0x12, 114, int)
210
211struct compat_floppy_drive_params {
212	char		cmos;
213	compat_ulong_t	max_dtr;
214	compat_ulong_t	hlt;
215	compat_ulong_t	hut;
216	compat_ulong_t	srt;
217	compat_ulong_t	spinup;
218	compat_ulong_t	spindown;
219	unsigned char	spindown_offset;
220	unsigned char	select_delay;
221	unsigned char	rps;
222	unsigned char	tracks;
223	compat_ulong_t	timeout;
224	unsigned char	interleave_sect;
225	struct floppy_max_errors max_errors;
226	char		flags;
227	char		read_track;
228	short		autodetect[8];
229	compat_int_t	checkfreq;
230	compat_int_t	native_format;
231};
232
233struct compat_floppy_drive_struct {
234	signed char	flags;
235	compat_ulong_t	spinup_date;
236	compat_ulong_t	select_date;
237	compat_ulong_t	first_read_date;
238	short		probed_format;
239	short		track;
240	short		maxblock;
241	short		maxtrack;
242	compat_int_t	generation;
243	compat_int_t	keep_data;
244	compat_int_t	fd_ref;
245	compat_int_t	fd_device;
246	compat_int_t	last_checked;
247	compat_caddr_t dmabuf;
248	compat_int_t	bufblocks;
249};
250
251struct compat_floppy_fdc_state {
252	compat_int_t	spec1;
253	compat_int_t	spec2;
254	compat_int_t	dtr;
255	unsigned char	version;
256	unsigned char	dor;
257	compat_ulong_t	address;
258	unsigned int	rawcmd:2;
259	unsigned int	reset:1;
260	unsigned int	need_configure:1;
261	unsigned int	perp_mode:2;
262	unsigned int	has_fifo:1;
263	unsigned int	driver_version;
264	unsigned char	track[4];
265};
266
267struct compat_floppy_write_errors {
268	unsigned int	write_errors;
269	compat_ulong_t	first_error_sector;
270	compat_int_t	first_error_generation;
271	compat_ulong_t	last_error_sector;
272	compat_int_t	last_error_generation;
273	compat_uint_t	badness;
274};
275
276#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
277#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
278#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
279#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
280#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
281#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
282#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
283#define FDWERRORGET32  _IOR(2, 0x17, struct compat_floppy_write_errors)
284
285static struct {
286	unsigned int	cmd32;
287	unsigned int	cmd;
288} fd_ioctl_trans_table[] = {
289	{ FDSETPRM32, FDSETPRM },
290	{ FDDEFPRM32, FDDEFPRM },
291	{ FDGETPRM32, FDGETPRM },
292	{ FDSETDRVPRM32, FDSETDRVPRM },
293	{ FDGETDRVPRM32, FDGETDRVPRM },
294	{ FDGETDRVSTAT32, FDGETDRVSTAT },
295	{ FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
296	{ FDGETFDCSTAT32, FDGETFDCSTAT },
297	{ FDWERRORGET32, FDWERRORGET }
298};
299
300#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table)
301
302static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode,
303		unsigned int cmd, unsigned long arg)
304{
305	mm_segment_t old_fs = get_fs();
306	void *karg = NULL;
307	unsigned int kcmd = 0;
308	int i, err;
309
310	for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
311		if (cmd == fd_ioctl_trans_table[i].cmd32) {
312			kcmd = fd_ioctl_trans_table[i].cmd;
313			break;
314		}
315	if (!kcmd)
316		return -EINVAL;
317
318	switch (cmd) {
319	case FDSETPRM32:
320	case FDDEFPRM32:
321	case FDGETPRM32:
322	{
323		compat_uptr_t name;
324		struct compat_floppy_struct __user *uf;
325		struct floppy_struct *f;
326
327		uf = compat_ptr(arg);
328		f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
329		if (!karg)
330			return -ENOMEM;
331		if (cmd == FDGETPRM32)
332			break;
333		err = __get_user(f->size, &uf->size);
334		err |= __get_user(f->sect, &uf->sect);
335		err |= __get_user(f->head, &uf->head);
336		err |= __get_user(f->track, &uf->track);
337		err |= __get_user(f->stretch, &uf->stretch);
338		err |= __get_user(f->gap, &uf->gap);
339		err |= __get_user(f->rate, &uf->rate);
340		err |= __get_user(f->spec1, &uf->spec1);
341		err |= __get_user(f->fmt_gap, &uf->fmt_gap);
342		err |= __get_user(name, &uf->name);
343		f->name = compat_ptr(name);
344		if (err) {
345			err = -EFAULT;
346			goto out;
347		}
348		break;
349	}
350	case FDSETDRVPRM32:
351	case FDGETDRVPRM32:
352	{
353		struct compat_floppy_drive_params __user *uf;
354		struct floppy_drive_params *f;
355
356		uf = compat_ptr(arg);
357		f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
358		if (!karg)
359			return -ENOMEM;
360		if (cmd == FDGETDRVPRM32)
361			break;
362		err = __get_user(f->cmos, &uf->cmos);
363		err |= __get_user(f->max_dtr, &uf->max_dtr);
364		err |= __get_user(f->hlt, &uf->hlt);
365		err |= __get_user(f->hut, &uf->hut);
366		err |= __get_user(f->srt, &uf->srt);
367		err |= __get_user(f->spinup, &uf->spinup);
368		err |= __get_user(f->spindown, &uf->spindown);
369		err |= __get_user(f->spindown_offset, &uf->spindown_offset);
370		err |= __get_user(f->select_delay, &uf->select_delay);
371		err |= __get_user(f->rps, &uf->rps);
372		err |= __get_user(f->tracks, &uf->tracks);
373		err |= __get_user(f->timeout, &uf->timeout);
374		err |= __get_user(f->interleave_sect, &uf->interleave_sect);
375		err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors));
376		err |= __get_user(f->flags, &uf->flags);
377		err |= __get_user(f->read_track, &uf->read_track);
378		err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect));
379		err |= __get_user(f->checkfreq, &uf->checkfreq);
380		err |= __get_user(f->native_format, &uf->native_format);
381		if (err) {
382			err = -EFAULT;
383			goto out;
384		}
385		break;
386	}
387	case FDGETDRVSTAT32:
388	case FDPOLLDRVSTAT32:
389		karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
390		if (!karg)
391			return -ENOMEM;
392		break;
393	case FDGETFDCSTAT32:
394		karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
395		if (!karg)
396			return -ENOMEM;
397		break;
398	case FDWERRORGET32:
399		karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
400		if (!karg)
401			return -ENOMEM;
402		break;
403	default:
404		return -EINVAL;
405	}
406	set_fs(KERNEL_DS);
407	err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg);
408	set_fs(old_fs);
409	if (err)
410		goto out;
411	switch (cmd) {
412	case FDGETPRM32:
413	{
414		struct floppy_struct *f = karg;
415		struct compat_floppy_struct __user *uf = compat_ptr(arg);
416
417		err = __put_user(f->size, &uf->size);
418		err |= __put_user(f->sect, &uf->sect);
419		err |= __put_user(f->head, &uf->head);
420		err |= __put_user(f->track, &uf->track);
421		err |= __put_user(f->stretch, &uf->stretch);
422		err |= __put_user(f->gap, &uf->gap);
423		err |= __put_user(f->rate, &uf->rate);
424		err |= __put_user(f->spec1, &uf->spec1);
425		err |= __put_user(f->fmt_gap, &uf->fmt_gap);
426		err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name);
427		break;
428	}
429	case FDGETDRVPRM32:
430	{
431		struct compat_floppy_drive_params __user *uf;
432		struct floppy_drive_params *f = karg;
433
434		uf = compat_ptr(arg);
435		err = __put_user(f->cmos, &uf->cmos);
436		err |= __put_user(f->max_dtr, &uf->max_dtr);
437		err |= __put_user(f->hlt, &uf->hlt);
438		err |= __put_user(f->hut, &uf->hut);
439		err |= __put_user(f->srt, &uf->srt);
440		err |= __put_user(f->spinup, &uf->spinup);
441		err |= __put_user(f->spindown, &uf->spindown);
442		err |= __put_user(f->spindown_offset, &uf->spindown_offset);
443		err |= __put_user(f->select_delay, &uf->select_delay);
444		err |= __put_user(f->rps, &uf->rps);
445		err |= __put_user(f->tracks, &uf->tracks);
446		err |= __put_user(f->timeout, &uf->timeout);
447		err |= __put_user(f->interleave_sect, &uf->interleave_sect);
448		err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors));
449		err |= __put_user(f->flags, &uf->flags);
450		err |= __put_user(f->read_track, &uf->read_track);
451		err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect));
452		err |= __put_user(f->checkfreq, &uf->checkfreq);
453		err |= __put_user(f->native_format, &uf->native_format);
454		break;
455	}
456	case FDGETDRVSTAT32:
457	case FDPOLLDRVSTAT32:
458	{
459		struct compat_floppy_drive_struct __user *uf;
460		struct floppy_drive_struct *f = karg;
461
462		uf = compat_ptr(arg);
463		err = __put_user(f->flags, &uf->flags);
464		err |= __put_user(f->spinup_date, &uf->spinup_date);
465		err |= __put_user(f->select_date, &uf->select_date);
466		err |= __put_user(f->first_read_date, &uf->first_read_date);
467		err |= __put_user(f->probed_format, &uf->probed_format);
468		err |= __put_user(f->track, &uf->track);
469		err |= __put_user(f->maxblock, &uf->maxblock);
470		err |= __put_user(f->maxtrack, &uf->maxtrack);
471		err |= __put_user(f->generation, &uf->generation);
472		err |= __put_user(f->keep_data, &uf->keep_data);
473		err |= __put_user(f->fd_ref, &uf->fd_ref);
474		err |= __put_user(f->fd_device, &uf->fd_device);
475		err |= __put_user(f->last_checked, &uf->last_checked);
476		err |= __put_user((u64)f->dmabuf, &uf->dmabuf);
477		err |= __put_user((u64)f->bufblocks, &uf->bufblocks);
478		break;
479	}
480	case FDGETFDCSTAT32:
481	{
482		struct compat_floppy_fdc_state __user *uf;
483		struct floppy_fdc_state *f = karg;
484
485		uf = compat_ptr(arg);
486		err = __put_user(f->spec1, &uf->spec1);
487		err |= __put_user(f->spec2, &uf->spec2);
488		err |= __put_user(f->dtr, &uf->dtr);
489		err |= __put_user(f->version, &uf->version);
490		err |= __put_user(f->dor, &uf->dor);
491		err |= __put_user(f->address, &uf->address);
492		err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address),
493				   (char *)&f->address + sizeof(f->address), sizeof(int));
494		err |= __put_user(f->driver_version, &uf->driver_version);
495		err |= __copy_to_user(uf->track, f->track, sizeof(f->track));
496		break;
497	}
498	case FDWERRORGET32:
499	{
500		struct compat_floppy_write_errors __user *uf;
501		struct floppy_write_errors *f = karg;
502
503		uf = compat_ptr(arg);
504		err = __put_user(f->write_errors, &uf->write_errors);
505		err |= __put_user(f->first_error_sector, &uf->first_error_sector);
506		err |= __put_user(f->first_error_generation, &uf->first_error_generation);
507		err |= __put_user(f->last_error_sector, &uf->last_error_sector);
508		err |= __put_user(f->last_error_generation, &uf->last_error_generation);
509		err |= __put_user(f->badness, &uf->badness);
510		break;
511	}
512	default:
513		break;
514	}
515	if (err)
516		err = -EFAULT;
517
518out:
519	kfree(karg);
520	return err;
521}
522
523static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode,
524			unsigned cmd, unsigned long arg)
525{
526	switch (cmd) {
527	case HDIO_GET_UNMASKINTR:
528	case HDIO_GET_MULTCOUNT:
529	case HDIO_GET_KEEPSETTINGS:
530	case HDIO_GET_32BIT:
531	case HDIO_GET_NOWERR:
532	case HDIO_GET_DMA:
533	case HDIO_GET_NICE:
534	case HDIO_GET_WCACHE:
535	case HDIO_GET_ACOUSTIC:
536	case HDIO_GET_ADDRESS:
537	case HDIO_GET_BUSSTATE:
538		return compat_hdio_ioctl(bdev, mode, cmd, arg);
539	case FDSETPRM32:
540	case FDDEFPRM32:
541	case FDGETPRM32:
542	case FDSETDRVPRM32:
543	case FDGETDRVPRM32:
544	case FDGETDRVSTAT32:
545	case FDPOLLDRVSTAT32:
546	case FDGETFDCSTAT32:
547	case FDWERRORGET32:
548		return compat_fd_ioctl(bdev, mode, cmd, arg);
549	case CDROMREADAUDIO:
550		return compat_cdrom_read_audio(bdev, mode, cmd, arg);
551	case CDROM_SEND_PACKET:
552		return compat_cdrom_generic_command(bdev, mode, cmd, arg);
553
554	/*
555	 * No handler required for the ones below, we just need to
556	 * convert arg to a 64 bit pointer.
557	 */
558	case BLKSECTSET:
559	/*
560	 * 0x03 -- HD/IDE ioctl's used by hdparm and friends.
561	 *         Some need translations, these do not.
562	 */
563	case HDIO_GET_IDENTITY:
564	case HDIO_DRIVE_TASK:
565	case HDIO_DRIVE_CMD:
566	/* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */
567	case 0x330:
568	/* 0x02 -- Floppy ioctls */
569	case FDMSGON:
570	case FDMSGOFF:
571	case FDSETEMSGTRESH:
572	case FDFLUSH:
573	case FDWERRORCLR:
574	case FDSETMAXERRS:
575	case FDGETMAXERRS:
576	case FDGETDRVTYP:
577	case FDEJECT:
578	case FDCLRPRM:
579	case FDFMTBEG:
580	case FDFMTEND:
581	case FDRESET:
582	case FDTWADDLE:
583	case FDFMTTRK:
584	case FDRAWCMD:
585	/* CDROM stuff */
586	case CDROMPAUSE:
587	case CDROMRESUME:
588	case CDROMPLAYMSF:
589	case CDROMPLAYTRKIND:
590	case CDROMREADTOCHDR:
591	case CDROMREADTOCENTRY:
592	case CDROMSTOP:
593	case CDROMSTART:
594	case CDROMEJECT:
595	case CDROMVOLCTRL:
596	case CDROMSUBCHNL:
597	case CDROMMULTISESSION:
598	case CDROM_GET_MCN:
599	case CDROMRESET:
600	case CDROMVOLREAD:
601	case CDROMSEEK:
602	case CDROMPLAYBLK:
603	case CDROMCLOSETRAY:
604	case CDROM_DISC_STATUS:
605	case CDROM_CHANGER_NSLOTS:
606	case CDROM_GET_CAPABILITY:
607	/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
608	 * not take a struct cdrom_read, instead they take a struct cdrom_msf
609	 * which is compatible.
610	 */
611	case CDROMREADMODE2:
612	case CDROMREADMODE1:
613	case CDROMREADRAW:
614	case CDROMREADCOOKED:
615	case CDROMREADALL:
616	/* DVD ioctls */
617	case DVD_READ_STRUCT:
618	case DVD_WRITE_STRUCT:
619	case DVD_AUTH:
620		arg = (unsigned long)compat_ptr(arg);
621	/* These intepret arg as an unsigned long, not as a pointer,
622	 * so we must not do compat_ptr() conversion. */
623	case HDIO_SET_MULTCOUNT:
624	case HDIO_SET_UNMASKINTR:
625	case HDIO_SET_KEEPSETTINGS:
626	case HDIO_SET_32BIT:
627	case HDIO_SET_NOWERR:
628	case HDIO_SET_DMA:
629	case HDIO_SET_PIO_MODE:
630	case HDIO_SET_NICE:
631	case HDIO_SET_WCACHE:
632	case HDIO_SET_ACOUSTIC:
633	case HDIO_SET_BUSSTATE:
634	case HDIO_SET_ADDRESS:
635	case CDROMEJECT_SW:
636	case CDROM_SET_OPTIONS:
637	case CDROM_CLEAR_OPTIONS:
638	case CDROM_SELECT_SPEED:
639	case CDROM_SELECT_DISC:
640	case CDROM_MEDIA_CHANGED:
641	case CDROM_DRIVE_STATUS:
642	case CDROM_LOCKDOOR:
643	case CDROM_DEBUG:
644		break;
645	default:
646		/* unknown ioctl number */
647		return -ENOIOCTLCMD;
648	}
649
650	return __blkdev_driver_ioctl(bdev, mode, cmd, arg);
651}
652
653/* Most of the generic ioctls are handled in the normal fallback path.
654   This assumes the blkdev's low level compat_ioctl always returns
655   ENOIOCTLCMD for unknown ioctls. */
656long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
657{
658	int ret = -ENOIOCTLCMD;
659	struct inode *inode = file->f_mapping->host;
660	struct block_device *bdev = inode->i_bdev;
661	struct gendisk *disk = bdev->bd_disk;
662	fmode_t mode = file->f_mode;
663	struct backing_dev_info *bdi;
664	loff_t size;
 
665
666	/*
667	 * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have
668	 * to updated it before every ioctl.
669	 */
670	if (file->f_flags & O_NDELAY)
671		mode |= FMODE_NDELAY;
672	else
673		mode &= ~FMODE_NDELAY;
674
675	switch (cmd) {
676	case HDIO_GETGEO:
677		return compat_hdio_getgeo(disk, bdev, compat_ptr(arg));
678	case BLKPBSZGET:
679		return compat_put_uint(arg, bdev_physical_block_size(bdev));
680	case BLKIOMIN:
681		return compat_put_uint(arg, bdev_io_min(bdev));
682	case BLKIOOPT:
683		return compat_put_uint(arg, bdev_io_opt(bdev));
684	case BLKALIGNOFF:
685		return compat_put_int(arg, bdev_alignment_offset(bdev));
686	case BLKDISCARDZEROES:
687		return compat_put_uint(arg, bdev_discard_zeroes_data(bdev));
688	case BLKFLSBUF:
689	case BLKROSET:
690	case BLKDISCARD:
691	case BLKSECDISCARD:
 
692	/*
693	 * the ones below are implemented in blkdev_locked_ioctl,
694	 * but we call blkdev_ioctl, which gets the lock for us
695	 */
696	case BLKRRPART:
697		return blkdev_ioctl(bdev, mode, cmd,
698				(unsigned long)compat_ptr(arg));
699	case BLKBSZSET_32:
700		return blkdev_ioctl(bdev, mode, BLKBSZSET,
701				(unsigned long)compat_ptr(arg));
702	case BLKPG:
703		return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg));
704	case BLKRAGET:
705	case BLKFRAGET:
706		if (!arg)
707			return -EINVAL;
708		bdi = blk_get_backing_dev_info(bdev);
709		if (bdi == NULL)
710			return -ENOTTY;
711		return compat_put_long(arg,
712				       (bdi->ra_pages * PAGE_CACHE_SIZE) / 512);
713	case BLKROGET: /* compatible */
714		return compat_put_int(arg, bdev_read_only(bdev) != 0);
715	case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
716		return compat_put_int(arg, block_size(bdev));
717	case BLKSSZGET: /* get block device hardware sector size */
718		return compat_put_int(arg, bdev_logical_block_size(bdev));
719	case BLKSECTGET:
 
 
 
 
720		return compat_put_ushort(arg,
721					 queue_max_sectors(bdev_get_queue(bdev)));
722	case BLKRASET: /* compatible, but no compat_ptr (!) */
723	case BLKFRASET:
724		if (!capable(CAP_SYS_ADMIN))
725			return -EACCES;
726		bdi = blk_get_backing_dev_info(bdev);
727		if (bdi == NULL)
728			return -ENOTTY;
729		bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE;
730		return 0;
731	case BLKGETSIZE:
732		size = i_size_read(bdev->bd_inode);
733		if ((size >> 9) > ~0UL)
734			return -EFBIG;
735		return compat_put_ulong(arg, size >> 9);
736
737	case BLKGETSIZE64_32:
738		return compat_put_u64(arg, i_size_read(bdev->bd_inode));
739
740	case BLKTRACESETUP32:
741	case BLKTRACESTART: /* compatible */
742	case BLKTRACESTOP:  /* compatible */
743	case BLKTRACETEARDOWN: /* compatible */
744		ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
745		return ret;
746	default:
747		if (disk->fops->compat_ioctl)
748			ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
749		if (ret == -ENOIOCTLCMD)
750			ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg);
751		return ret;
752	}
753}
v4.17
  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
 14static int compat_put_ushort(unsigned long arg, unsigned short val)
 15{
 16	return put_user(val, (unsigned short __user *)compat_ptr(arg));
 17}
 18
 19static int compat_put_int(unsigned long arg, int val)
 20{
 21	return put_user(val, (compat_int_t __user *)compat_ptr(arg));
 22}
 23
 24static 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
 29static int compat_put_long(unsigned long arg, long val)
 30{
 31	return put_user(val, (compat_long_t __user *)compat_ptr(arg));
 32}
 33
 34static 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
 39static int compat_put_u64(unsigned long arg, u64 val)
 40{
 41	return put_user(val, (compat_u64 __user *)compat_ptr(arg));
 42}
 43
 44struct compat_hd_geometry {
 45	unsigned char heads;
 46	unsigned char sectors;
 47	unsigned short cylinders;
 48	u32 start;
 49};
 50
 51static 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
 80static 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
 98struct 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
105struct 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
117static 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
144static 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
176struct 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
183static 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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209static 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. */
315long 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}