v4l2-compat-ioctl32.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. /*
  2. * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  3. * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
  4. *
  5. * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
  6. * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
  7. * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
  8. * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz)
  9. * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
  10. * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
  11. *
  12. * These routines maintain argument size conversion between 32bit and 64bit
  13. * ioctls.
  14. */
  15. #include <linux/compat.h>
  16. #include <linux/module.h>
  17. #include <linux/videodev2.h>
  18. #include <linux/v4l2-subdev.h>
  19. #include <media/v4l2-dev.h>
  20. #include <media/v4l2-fh.h>
  21. #include <media/v4l2-ctrls.h>
  22. #include <media/v4l2-ioctl.h>
  23. static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  24. {
  25. long ret = -ENOIOCTLCMD;
  26. if (file->f_op->unlocked_ioctl)
  27. ret = file->f_op->unlocked_ioctl(file, cmd, arg);
  28. return ret;
  29. }
  30. struct v4l2_clip32 {
  31. struct v4l2_rect c;
  32. compat_caddr_t next;
  33. };
  34. struct v4l2_window32 {
  35. struct v4l2_rect w;
  36. __u32 field; /* enum v4l2_field */
  37. __u32 chromakey;
  38. compat_caddr_t clips; /* actually struct v4l2_clip32 * */
  39. __u32 clipcount;
  40. compat_caddr_t bitmap;
  41. __u8 global_alpha;
  42. };
  43. static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
  44. {
  45. struct v4l2_clip32 __user *uclips;
  46. struct v4l2_clip __user *kclips;
  47. compat_caddr_t p;
  48. u32 n;
  49. if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
  50. copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
  51. get_user(kp->field, &up->field) ||
  52. get_user(kp->chromakey, &up->chromakey) ||
  53. get_user(kp->clipcount, &up->clipcount) ||
  54. get_user(kp->global_alpha, &up->global_alpha))
  55. return -EFAULT;
  56. if (kp->clipcount > 2048)
  57. return -EINVAL;
  58. if (!kp->clipcount) {
  59. kp->clips = NULL;
  60. return 0;
  61. }
  62. n = kp->clipcount;
  63. if (get_user(p, &up->clips))
  64. return -EFAULT;
  65. uclips = compat_ptr(p);
  66. kclips = compat_alloc_user_space(n * sizeof(*kclips));
  67. kp->clips = kclips;
  68. while (n--) {
  69. if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
  70. return -EFAULT;
  71. if (put_user(n ? kclips + 1 : NULL, &kclips->next))
  72. return -EFAULT;
  73. uclips++;
  74. kclips++;
  75. }
  76. return 0;
  77. }
  78. static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
  79. {
  80. struct v4l2_clip __user *kclips = kp->clips;
  81. struct v4l2_clip32 __user *uclips;
  82. u32 n = kp->clipcount;
  83. compat_caddr_t p;
  84. if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) ||
  85. put_user(kp->field, &up->field) ||
  86. put_user(kp->chromakey, &up->chromakey) ||
  87. put_user(kp->clipcount, &up->clipcount) ||
  88. put_user(kp->global_alpha, &up->global_alpha))
  89. return -EFAULT;
  90. if (!kp->clipcount)
  91. return 0;
  92. if (get_user(p, &up->clips))
  93. return -EFAULT;
  94. uclips = compat_ptr(p);
  95. while (n--) {
  96. if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
  97. return -EFAULT;
  98. uclips++;
  99. kclips++;
  100. }
  101. return 0;
  102. }
  103. struct v4l2_format32 {
  104. __u32 type; /* enum v4l2_buf_type */
  105. union {
  106. struct v4l2_pix_format pix;
  107. struct v4l2_pix_format_mplane pix_mp;
  108. struct v4l2_window32 win;
  109. struct v4l2_vbi_format vbi;
  110. struct v4l2_sliced_vbi_format sliced;
  111. struct v4l2_sdr_format sdr;
  112. struct v4l2_meta_format meta;
  113. __u8 raw_data[200]; /* user-defined */
  114. } fmt;
  115. };
  116. /**
  117. * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
  118. * @index: on return, index of the first created buffer
  119. * @count: entry: number of requested buffers,
  120. * return: number of created buffers
  121. * @memory: buffer memory type
  122. * @format: frame format, for which buffers are requested
  123. * @reserved: future extensions
  124. */
  125. struct v4l2_create_buffers32 {
  126. __u32 index;
  127. __u32 count;
  128. __u32 memory; /* enum v4l2_memory */
  129. struct v4l2_format32 format;
  130. __u32 reserved[8];
  131. };
  132. static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
  133. {
  134. if (get_user(kp->type, &up->type))
  135. return -EFAULT;
  136. switch (kp->type) {
  137. case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  138. case V4L2_BUF_TYPE_VIDEO_OUTPUT:
  139. return copy_from_user(&kp->fmt.pix, &up->fmt.pix,
  140. sizeof(kp->fmt.pix)) ? -EFAULT : 0;
  141. case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
  142. case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
  143. return copy_from_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
  144. sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
  145. case V4L2_BUF_TYPE_VIDEO_OVERLAY:
  146. case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
  147. return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
  148. case V4L2_BUF_TYPE_VBI_CAPTURE:
  149. case V4L2_BUF_TYPE_VBI_OUTPUT:
  150. return copy_from_user(&kp->fmt.vbi, &up->fmt.vbi,
  151. sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
  152. case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
  153. case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
  154. return copy_from_user(&kp->fmt.sliced, &up->fmt.sliced,
  155. sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
  156. case V4L2_BUF_TYPE_SDR_CAPTURE:
  157. case V4L2_BUF_TYPE_SDR_OUTPUT:
  158. return copy_from_user(&kp->fmt.sdr, &up->fmt.sdr,
  159. sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
  160. case V4L2_BUF_TYPE_META_CAPTURE:
  161. return copy_from_user(&kp->fmt.meta, &up->fmt.meta,
  162. sizeof(kp->fmt.meta)) ? -EFAULT : 0;
  163. default:
  164. pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
  165. kp->type);
  166. return -EINVAL;
  167. }
  168. }
  169. static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
  170. {
  171. if (!access_ok(VERIFY_READ, up, sizeof(*up)))
  172. return -EFAULT;
  173. return __get_v4l2_format32(kp, up);
  174. }
  175. static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
  176. {
  177. if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
  178. copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format)))
  179. return -EFAULT;
  180. return __get_v4l2_format32(&kp->format, &up->format);
  181. }
  182. static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
  183. {
  184. if (put_user(kp->type, &up->type))
  185. return -EFAULT;
  186. switch (kp->type) {
  187. case V4L2_BUF_TYPE_VIDEO_CAPTURE:
  188. case V4L2_BUF_TYPE_VIDEO_OUTPUT:
  189. return copy_to_user(&up->fmt.pix, &kp->fmt.pix,
  190. sizeof(kp->fmt.pix)) ? -EFAULT : 0;
  191. case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
  192. case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
  193. return copy_to_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
  194. sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
  195. case V4L2_BUF_TYPE_VIDEO_OVERLAY:
  196. case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
  197. return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
  198. case V4L2_BUF_TYPE_VBI_CAPTURE:
  199. case V4L2_BUF_TYPE_VBI_OUTPUT:
  200. return copy_to_user(&up->fmt.vbi, &kp->fmt.vbi,
  201. sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
  202. case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
  203. case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
  204. return copy_to_user(&up->fmt.sliced, &kp->fmt.sliced,
  205. sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
  206. case V4L2_BUF_TYPE_SDR_CAPTURE:
  207. case V4L2_BUF_TYPE_SDR_OUTPUT:
  208. return copy_to_user(&up->fmt.sdr, &kp->fmt.sdr,
  209. sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
  210. case V4L2_BUF_TYPE_META_CAPTURE:
  211. return copy_to_user(&up->fmt.meta, &kp->fmt.meta,
  212. sizeof(kp->fmt.meta)) ? -EFAULT : 0;
  213. default:
  214. pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
  215. kp->type);
  216. return -EINVAL;
  217. }
  218. }
  219. static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
  220. {
  221. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
  222. return -EFAULT;
  223. return __put_v4l2_format32(kp, up);
  224. }
  225. static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
  226. {
  227. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
  228. copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
  229. copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
  230. return -EFAULT;
  231. return __put_v4l2_format32(&kp->format, &up->format);
  232. }
  233. struct v4l2_standard32 {
  234. __u32 index;
  235. compat_u64 id;
  236. __u8 name[24];
  237. struct v4l2_fract frameperiod; /* Frames, not fields */
  238. __u32 framelines;
  239. __u32 reserved[4];
  240. };
  241. static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
  242. {
  243. /* other fields are not set by the user, nor used by the driver */
  244. if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
  245. get_user(kp->index, &up->index))
  246. return -EFAULT;
  247. return 0;
  248. }
  249. static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
  250. {
  251. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
  252. put_user(kp->index, &up->index) ||
  253. put_user(kp->id, &up->id) ||
  254. copy_to_user(up->name, kp->name, sizeof(up->name)) ||
  255. copy_to_user(&up->frameperiod, &kp->frameperiod,
  256. sizeof(kp->frameperiod)) ||
  257. put_user(kp->framelines, &up->framelines) ||
  258. copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
  259. return -EFAULT;
  260. return 0;
  261. }
  262. struct v4l2_plane32 {
  263. __u32 bytesused;
  264. __u32 length;
  265. union {
  266. __u32 mem_offset;
  267. compat_long_t userptr;
  268. __s32 fd;
  269. } m;
  270. __u32 data_offset;
  271. __u32 reserved[11];
  272. };
  273. struct v4l2_buffer32 {
  274. __u32 index;
  275. __u32 type; /* enum v4l2_buf_type */
  276. __u32 bytesused;
  277. __u32 flags;
  278. __u32 field; /* enum v4l2_field */
  279. struct compat_timeval timestamp;
  280. struct v4l2_timecode timecode;
  281. __u32 sequence;
  282. /* memory location */
  283. __u32 memory; /* enum v4l2_memory */
  284. union {
  285. __u32 offset;
  286. compat_long_t userptr;
  287. compat_caddr_t planes;
  288. __s32 fd;
  289. } m;
  290. __u32 length;
  291. __u32 reserved2;
  292. __u32 reserved;
  293. };
  294. static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
  295. enum v4l2_memory memory)
  296. {
  297. void __user *up_pln;
  298. compat_long_t p;
  299. if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
  300. copy_in_user(&up->data_offset, &up32->data_offset,
  301. sizeof(up->data_offset)))
  302. return -EFAULT;
  303. switch (memory) {
  304. case V4L2_MEMORY_MMAP:
  305. case V4L2_MEMORY_OVERLAY:
  306. if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
  307. sizeof(up32->m.mem_offset)))
  308. return -EFAULT;
  309. break;
  310. case V4L2_MEMORY_USERPTR:
  311. if (get_user(p, &up32->m.userptr))
  312. return -EFAULT;
  313. up_pln = compat_ptr(p);
  314. if (put_user((unsigned long)up_pln, &up->m.userptr))
  315. return -EFAULT;
  316. break;
  317. case V4L2_MEMORY_DMABUF:
  318. if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
  319. return -EFAULT;
  320. break;
  321. }
  322. return 0;
  323. }
  324. static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
  325. enum v4l2_memory memory)
  326. {
  327. unsigned long p;
  328. if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
  329. copy_in_user(&up32->data_offset, &up->data_offset,
  330. sizeof(up->data_offset)))
  331. return -EFAULT;
  332. switch (memory) {
  333. case V4L2_MEMORY_MMAP:
  334. case V4L2_MEMORY_OVERLAY:
  335. if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
  336. sizeof(up->m.mem_offset)))
  337. return -EFAULT;
  338. break;
  339. case V4L2_MEMORY_USERPTR:
  340. if (get_user(p, &up->m.userptr) ||
  341. put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
  342. &up32->m.userptr))
  343. return -EFAULT;
  344. break;
  345. case V4L2_MEMORY_DMABUF:
  346. if (copy_in_user(&up32->m.fd, &up->m.fd,
  347. sizeof(up->m.fd)))
  348. return -EFAULT;
  349. break;
  350. }
  351. return 0;
  352. }
  353. static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
  354. {
  355. struct v4l2_plane32 __user *uplane32;
  356. struct v4l2_plane __user *uplane;
  357. compat_caddr_t p;
  358. int ret;
  359. if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
  360. get_user(kp->index, &up->index) ||
  361. get_user(kp->type, &up->type) ||
  362. get_user(kp->flags, &up->flags) ||
  363. get_user(kp->memory, &up->memory) ||
  364. get_user(kp->length, &up->length))
  365. return -EFAULT;
  366. if (V4L2_TYPE_IS_OUTPUT(kp->type))
  367. if (get_user(kp->bytesused, &up->bytesused) ||
  368. get_user(kp->field, &up->field) ||
  369. get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
  370. get_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec))
  371. return -EFAULT;
  372. if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
  373. unsigned int num_planes;
  374. if (kp->length == 0) {
  375. kp->m.planes = NULL;
  376. /* num_planes == 0 is legal, e.g. when userspace doesn't
  377. * need planes array on DQBUF*/
  378. return 0;
  379. } else if (kp->length > VIDEO_MAX_PLANES) {
  380. return -EINVAL;
  381. }
  382. if (get_user(p, &up->m.planes))
  383. return -EFAULT;
  384. uplane32 = compat_ptr(p);
  385. if (!access_ok(VERIFY_READ, uplane32,
  386. kp->length * sizeof(*uplane32)))
  387. return -EFAULT;
  388. /* We don't really care if userspace decides to kill itself
  389. * by passing a very big num_planes value */
  390. uplane = compat_alloc_user_space(kp->length * sizeof(*uplane));
  391. kp->m.planes = (__force struct v4l2_plane *)uplane;
  392. for (num_planes = 0; num_planes < kp->length; num_planes++) {
  393. ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
  394. if (ret)
  395. return ret;
  396. ++uplane;
  397. ++uplane32;
  398. }
  399. } else {
  400. switch (kp->memory) {
  401. case V4L2_MEMORY_MMAP:
  402. case V4L2_MEMORY_OVERLAY:
  403. if (get_user(kp->m.offset, &up->m.offset))
  404. return -EFAULT;
  405. break;
  406. case V4L2_MEMORY_USERPTR:
  407. {
  408. compat_long_t tmp;
  409. if (get_user(tmp, &up->m.userptr))
  410. return -EFAULT;
  411. kp->m.userptr = (unsigned long)compat_ptr(tmp);
  412. }
  413. break;
  414. case V4L2_MEMORY_DMABUF:
  415. if (get_user(kp->m.fd, &up->m.fd))
  416. return -EFAULT;
  417. break;
  418. }
  419. }
  420. return 0;
  421. }
  422. static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
  423. {
  424. struct v4l2_plane32 __user *uplane32;
  425. struct v4l2_plane __user *uplane;
  426. compat_caddr_t p;
  427. int num_planes;
  428. int ret;
  429. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
  430. put_user(kp->index, &up->index) ||
  431. put_user(kp->type, &up->type) ||
  432. put_user(kp->flags, &up->flags) ||
  433. put_user(kp->memory, &up->memory))
  434. return -EFAULT;
  435. if (put_user(kp->bytesused, &up->bytesused) ||
  436. put_user(kp->field, &up->field) ||
  437. put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
  438. put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
  439. copy_to_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
  440. put_user(kp->sequence, &up->sequence) ||
  441. put_user(kp->reserved2, &up->reserved2) ||
  442. put_user(kp->reserved, &up->reserved) ||
  443. put_user(kp->length, &up->length))
  444. return -EFAULT;
  445. if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
  446. num_planes = kp->length;
  447. if (num_planes == 0)
  448. return 0;
  449. uplane = (__force struct v4l2_plane __user *)kp->m.planes;
  450. if (get_user(p, &up->m.planes))
  451. return -EFAULT;
  452. uplane32 = compat_ptr(p);
  453. while (--num_planes >= 0) {
  454. ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
  455. if (ret)
  456. return ret;
  457. ++uplane;
  458. ++uplane32;
  459. }
  460. } else {
  461. switch (kp->memory) {
  462. case V4L2_MEMORY_MMAP:
  463. case V4L2_MEMORY_OVERLAY:
  464. if (put_user(kp->m.offset, &up->m.offset))
  465. return -EFAULT;
  466. break;
  467. case V4L2_MEMORY_USERPTR:
  468. if (put_user(kp->m.userptr, &up->m.userptr))
  469. return -EFAULT;
  470. break;
  471. case V4L2_MEMORY_DMABUF:
  472. if (put_user(kp->m.fd, &up->m.fd))
  473. return -EFAULT;
  474. break;
  475. }
  476. }
  477. return 0;
  478. }
  479. struct v4l2_framebuffer32 {
  480. __u32 capability;
  481. __u32 flags;
  482. compat_caddr_t base;
  483. struct {
  484. __u32 width;
  485. __u32 height;
  486. __u32 pixelformat;
  487. __u32 field;
  488. __u32 bytesperline;
  489. __u32 sizeimage;
  490. __u32 colorspace;
  491. __u32 priv;
  492. } fmt;
  493. };
  494. static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
  495. {
  496. u32 tmp;
  497. if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
  498. get_user(tmp, &up->base) ||
  499. get_user(kp->capability, &up->capability) ||
  500. get_user(kp->flags, &up->flags) ||
  501. copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
  502. return -EFAULT;
  503. kp->base = (__force void *)compat_ptr(tmp);
  504. return 0;
  505. }
  506. static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
  507. {
  508. u32 tmp = (u32)((unsigned long)kp->base);
  509. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
  510. put_user(tmp, &up->base) ||
  511. put_user(kp->capability, &up->capability) ||
  512. put_user(kp->flags, &up->flags) ||
  513. copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
  514. return -EFAULT;
  515. return 0;
  516. }
  517. struct v4l2_input32 {
  518. __u32 index; /* Which input */
  519. __u8 name[32]; /* Label */
  520. __u32 type; /* Type of input */
  521. __u32 audioset; /* Associated audios (bitfield) */
  522. __u32 tuner; /* Associated tuner */
  523. compat_u64 std;
  524. __u32 status;
  525. __u32 capabilities;
  526. __u32 reserved[3];
  527. };
  528. /* The 64-bit v4l2_input struct has extra padding at the end of the struct.
  529. Otherwise it is identical to the 32-bit version. */
  530. static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
  531. {
  532. if (copy_from_user(kp, up, sizeof(*up)))
  533. return -EFAULT;
  534. return 0;
  535. }
  536. static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
  537. {
  538. if (copy_to_user(up, kp, sizeof(*up)))
  539. return -EFAULT;
  540. return 0;
  541. }
  542. struct v4l2_ext_controls32 {
  543. __u32 which;
  544. __u32 count;
  545. __u32 error_idx;
  546. __u32 reserved[2];
  547. compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
  548. };
  549. struct v4l2_ext_control32 {
  550. __u32 id;
  551. __u32 size;
  552. __u32 reserved2[1];
  553. union {
  554. __s32 value;
  555. __s64 value64;
  556. compat_caddr_t string; /* actually char * */
  557. };
  558. } __attribute__ ((packed));
  559. /* Return true if this control is a pointer type. */
  560. static inline bool ctrl_is_pointer(struct file *file, u32 id)
  561. {
  562. struct video_device *vdev = video_devdata(file);
  563. struct v4l2_fh *fh = NULL;
  564. struct v4l2_ctrl_handler *hdl = NULL;
  565. struct v4l2_query_ext_ctrl qec = { id };
  566. const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
  567. if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
  568. fh = file->private_data;
  569. if (fh && fh->ctrl_handler)
  570. hdl = fh->ctrl_handler;
  571. else if (vdev->ctrl_handler)
  572. hdl = vdev->ctrl_handler;
  573. if (hdl) {
  574. struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
  575. return ctrl && ctrl->is_ptr;
  576. }
  577. if (!ops->vidioc_query_ext_ctrl)
  578. return false;
  579. return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
  580. (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
  581. }
  582. static int get_v4l2_ext_controls32(struct file *file,
  583. struct v4l2_ext_controls *kp,
  584. struct v4l2_ext_controls32 __user *up)
  585. {
  586. struct v4l2_ext_control32 __user *ucontrols;
  587. struct v4l2_ext_control __user *kcontrols;
  588. unsigned int n;
  589. compat_caddr_t p;
  590. if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
  591. get_user(kp->which, &up->which) ||
  592. get_user(kp->count, &up->count) ||
  593. get_user(kp->error_idx, &up->error_idx) ||
  594. copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
  595. return -EFAULT;
  596. if (kp->count == 0) {
  597. kp->controls = NULL;
  598. return 0;
  599. } else if (kp->count > V4L2_CID_MAX_CTRLS) {
  600. return -EINVAL;
  601. }
  602. if (get_user(p, &up->controls))
  603. return -EFAULT;
  604. ucontrols = compat_ptr(p);
  605. if (!access_ok(VERIFY_READ, ucontrols, kp->count * sizeof(*ucontrols)))
  606. return -EFAULT;
  607. kcontrols = compat_alloc_user_space(kp->count * sizeof(*kcontrols));
  608. kp->controls = (__force struct v4l2_ext_control *)kcontrols;
  609. for (n = 0; n < kp->count; n++) {
  610. u32 id;
  611. if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
  612. return -EFAULT;
  613. if (get_user(id, &kcontrols->id))
  614. return -EFAULT;
  615. if (ctrl_is_pointer(file, id)) {
  616. void __user *s;
  617. if (get_user(p, &ucontrols->string))
  618. return -EFAULT;
  619. s = compat_ptr(p);
  620. if (put_user(s, &kcontrols->string))
  621. return -EFAULT;
  622. }
  623. ucontrols++;
  624. kcontrols++;
  625. }
  626. return 0;
  627. }
  628. static int put_v4l2_ext_controls32(struct file *file,
  629. struct v4l2_ext_controls *kp,
  630. struct v4l2_ext_controls32 __user *up)
  631. {
  632. struct v4l2_ext_control32 __user *ucontrols;
  633. struct v4l2_ext_control __user *kcontrols =
  634. (__force struct v4l2_ext_control __user *)kp->controls;
  635. int n = kp->count;
  636. compat_caddr_t p;
  637. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
  638. put_user(kp->which, &up->which) ||
  639. put_user(kp->count, &up->count) ||
  640. put_user(kp->error_idx, &up->error_idx) ||
  641. copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
  642. return -EFAULT;
  643. if (!kp->count)
  644. return 0;
  645. if (get_user(p, &up->controls))
  646. return -EFAULT;
  647. ucontrols = compat_ptr(p);
  648. if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(*ucontrols)))
  649. return -EFAULT;
  650. while (--n >= 0) {
  651. unsigned size = sizeof(*ucontrols);
  652. u32 id;
  653. if (get_user(id, &kcontrols->id))
  654. return -EFAULT;
  655. /* Do not modify the pointer when copying a pointer control.
  656. The contents of the pointer was changed, not the pointer
  657. itself. */
  658. if (ctrl_is_pointer(file, id))
  659. size -= sizeof(ucontrols->value64);
  660. if (copy_in_user(ucontrols, kcontrols, size))
  661. return -EFAULT;
  662. ucontrols++;
  663. kcontrols++;
  664. }
  665. return 0;
  666. }
  667. struct v4l2_event32 {
  668. __u32 type;
  669. union {
  670. compat_s64 value64;
  671. __u8 data[64];
  672. } u;
  673. __u32 pending;
  674. __u32 sequence;
  675. struct compat_timespec timestamp;
  676. __u32 id;
  677. __u32 reserved[8];
  678. };
  679. static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *up)
  680. {
  681. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
  682. put_user(kp->type, &up->type) ||
  683. copy_to_user(&up->u, &kp->u, sizeof(kp->u)) ||
  684. put_user(kp->pending, &up->pending) ||
  685. put_user(kp->sequence, &up->sequence) ||
  686. put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
  687. put_user(kp->timestamp.tv_nsec, &up->timestamp.tv_nsec) ||
  688. put_user(kp->id, &up->id) ||
  689. copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
  690. return -EFAULT;
  691. return 0;
  692. }
  693. struct v4l2_edid32 {
  694. __u32 pad;
  695. __u32 start_block;
  696. __u32 blocks;
  697. __u32 reserved[5];
  698. compat_caddr_t edid;
  699. };
  700. static int get_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
  701. {
  702. u32 tmp;
  703. if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
  704. get_user(kp->pad, &up->pad) ||
  705. get_user(kp->start_block, &up->start_block) ||
  706. get_user(kp->blocks, &up->blocks) ||
  707. get_user(tmp, &up->edid) ||
  708. copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
  709. return -EFAULT;
  710. kp->edid = (__force u8 *)compat_ptr(tmp);
  711. return 0;
  712. }
  713. static int put_v4l2_edid32(struct v4l2_edid *kp, struct v4l2_edid32 __user *up)
  714. {
  715. u32 tmp = (u32)((unsigned long)kp->edid);
  716. if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
  717. put_user(kp->pad, &up->pad) ||
  718. put_user(kp->start_block, &up->start_block) ||
  719. put_user(kp->blocks, &up->blocks) ||
  720. put_user(tmp, &up->edid) ||
  721. copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
  722. return -EFAULT;
  723. return 0;
  724. }
  725. #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
  726. #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
  727. #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
  728. #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
  729. #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
  730. #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
  731. #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
  732. #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
  733. #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
  734. #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
  735. #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
  736. #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
  737. #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
  738. #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
  739. #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
  740. #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
  741. #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
  742. #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
  743. #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
  744. #define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
  745. #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
  746. #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
  747. #define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
  748. #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
  749. #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
  750. static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  751. {
  752. union {
  753. struct v4l2_format v2f;
  754. struct v4l2_buffer v2b;
  755. struct v4l2_framebuffer v2fb;
  756. struct v4l2_input v2i;
  757. struct v4l2_standard v2s;
  758. struct v4l2_ext_controls v2ecs;
  759. struct v4l2_event v2ev;
  760. struct v4l2_create_buffers v2crt;
  761. struct v4l2_edid v2edid;
  762. unsigned long vx;
  763. int vi;
  764. } karg;
  765. void __user *up = compat_ptr(arg);
  766. int compatible_arg = 1;
  767. long err = 0;
  768. /* First, convert the command. */
  769. switch (cmd) {
  770. case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
  771. case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
  772. case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
  773. case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
  774. case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
  775. case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
  776. case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
  777. case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
  778. case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
  779. case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
  780. case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
  781. case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
  782. case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
  783. case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
  784. case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
  785. case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
  786. case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
  787. case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
  788. case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
  789. case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
  790. case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
  791. case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
  792. case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
  793. case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
  794. case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
  795. }
  796. switch (cmd) {
  797. case VIDIOC_OVERLAY:
  798. case VIDIOC_STREAMON:
  799. case VIDIOC_STREAMOFF:
  800. case VIDIOC_S_INPUT:
  801. case VIDIOC_S_OUTPUT:
  802. err = get_user(karg.vi, (s32 __user *)up);
  803. compatible_arg = 0;
  804. break;
  805. case VIDIOC_G_INPUT:
  806. case VIDIOC_G_OUTPUT:
  807. compatible_arg = 0;
  808. break;
  809. case VIDIOC_G_EDID:
  810. case VIDIOC_S_EDID:
  811. err = get_v4l2_edid32(&karg.v2edid, up);
  812. compatible_arg = 0;
  813. break;
  814. case VIDIOC_G_FMT:
  815. case VIDIOC_S_FMT:
  816. case VIDIOC_TRY_FMT:
  817. err = get_v4l2_format32(&karg.v2f, up);
  818. compatible_arg = 0;
  819. break;
  820. case VIDIOC_CREATE_BUFS:
  821. err = get_v4l2_create32(&karg.v2crt, up);
  822. compatible_arg = 0;
  823. break;
  824. case VIDIOC_PREPARE_BUF:
  825. case VIDIOC_QUERYBUF:
  826. case VIDIOC_QBUF:
  827. case VIDIOC_DQBUF:
  828. err = get_v4l2_buffer32(&karg.v2b, up);
  829. compatible_arg = 0;
  830. break;
  831. case VIDIOC_S_FBUF:
  832. err = get_v4l2_framebuffer32(&karg.v2fb, up);
  833. compatible_arg = 0;
  834. break;
  835. case VIDIOC_G_FBUF:
  836. compatible_arg = 0;
  837. break;
  838. case VIDIOC_ENUMSTD:
  839. err = get_v4l2_standard32(&karg.v2s, up);
  840. compatible_arg = 0;
  841. break;
  842. case VIDIOC_ENUMINPUT:
  843. err = get_v4l2_input32(&karg.v2i, up);
  844. compatible_arg = 0;
  845. break;
  846. case VIDIOC_G_EXT_CTRLS:
  847. case VIDIOC_S_EXT_CTRLS:
  848. case VIDIOC_TRY_EXT_CTRLS:
  849. err = get_v4l2_ext_controls32(file, &karg.v2ecs, up);
  850. compatible_arg = 0;
  851. break;
  852. case VIDIOC_DQEVENT:
  853. compatible_arg = 0;
  854. break;
  855. }
  856. if (err)
  857. return err;
  858. if (compatible_arg)
  859. err = native_ioctl(file, cmd, (unsigned long)up);
  860. else {
  861. mm_segment_t old_fs = get_fs();
  862. set_fs(KERNEL_DS);
  863. err = native_ioctl(file, cmd, (unsigned long)&karg);
  864. set_fs(old_fs);
  865. }
  866. /* Special case: even after an error we need to put the
  867. results back for these ioctls since the error_idx will
  868. contain information on which control failed. */
  869. switch (cmd) {
  870. case VIDIOC_G_EXT_CTRLS:
  871. case VIDIOC_S_EXT_CTRLS:
  872. case VIDIOC_TRY_EXT_CTRLS:
  873. if (put_v4l2_ext_controls32(file, &karg.v2ecs, up))
  874. err = -EFAULT;
  875. break;
  876. case VIDIOC_S_EDID:
  877. if (put_v4l2_edid32(&karg.v2edid, up))
  878. err = -EFAULT;
  879. break;
  880. }
  881. if (err)
  882. return err;
  883. switch (cmd) {
  884. case VIDIOC_S_INPUT:
  885. case VIDIOC_S_OUTPUT:
  886. case VIDIOC_G_INPUT:
  887. case VIDIOC_G_OUTPUT:
  888. err = put_user(((s32)karg.vi), (s32 __user *)up);
  889. break;
  890. case VIDIOC_G_FBUF:
  891. err = put_v4l2_framebuffer32(&karg.v2fb, up);
  892. break;
  893. case VIDIOC_DQEVENT:
  894. err = put_v4l2_event32(&karg.v2ev, up);
  895. break;
  896. case VIDIOC_G_EDID:
  897. err = put_v4l2_edid32(&karg.v2edid, up);
  898. break;
  899. case VIDIOC_G_FMT:
  900. case VIDIOC_S_FMT:
  901. case VIDIOC_TRY_FMT:
  902. err = put_v4l2_format32(&karg.v2f, up);
  903. break;
  904. case VIDIOC_CREATE_BUFS:
  905. err = put_v4l2_create32(&karg.v2crt, up);
  906. break;
  907. case VIDIOC_PREPARE_BUF:
  908. case VIDIOC_QUERYBUF:
  909. case VIDIOC_QBUF:
  910. case VIDIOC_DQBUF:
  911. err = put_v4l2_buffer32(&karg.v2b, up);
  912. break;
  913. case VIDIOC_ENUMSTD:
  914. err = put_v4l2_standard32(&karg.v2s, up);
  915. break;
  916. case VIDIOC_ENUMINPUT:
  917. err = put_v4l2_input32(&karg.v2i, up);
  918. break;
  919. }
  920. return err;
  921. }
  922. long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
  923. {
  924. struct video_device *vdev = video_devdata(file);
  925. long ret = -ENOIOCTLCMD;
  926. if (!file->f_op->unlocked_ioctl)
  927. return ret;
  928. if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
  929. ret = do_video_ioctl(file, cmd, arg);
  930. else if (vdev->fops->compat_ioctl32)
  931. ret = vdev->fops->compat_ioctl32(file, cmd, arg);
  932. if (ret == -ENOIOCTLCMD)
  933. pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
  934. _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
  935. return ret;
  936. }
  937. EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);