compat_ioctl.c 11 KB

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