diff options
Diffstat (limited to 'fs/compat.c')
-rw-r--r-- | fs/compat.c | 122 |
1 files changed, 23 insertions, 99 deletions
diff --git a/fs/compat.c b/fs/compat.c index 6b06b6bae35e..ac3fb9ed8eea 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -310,96 +310,6 @@ static int __init init_sys32_ioctl(void) | |||
310 | 310 | ||
311 | __initcall(init_sys32_ioctl); | 311 | __initcall(init_sys32_ioctl); |
312 | 312 | ||
313 | int register_ioctl32_conversion(unsigned int cmd, | ||
314 | ioctl_trans_handler_t handler) | ||
315 | { | ||
316 | struct ioctl_trans *t; | ||
317 | struct ioctl_trans *new_t; | ||
318 | unsigned long hash = ioctl32_hash(cmd); | ||
319 | |||
320 | new_t = kmalloc(sizeof(*new_t), GFP_KERNEL); | ||
321 | if (!new_t) | ||
322 | return -ENOMEM; | ||
323 | |||
324 | down_write(&ioctl32_sem); | ||
325 | for (t = ioctl32_hash_table[hash]; t; t = t->next) { | ||
326 | if (t->cmd == cmd) { | ||
327 | printk(KERN_ERR "Trying to register duplicated ioctl32 " | ||
328 | "handler %x\n", cmd); | ||
329 | up_write(&ioctl32_sem); | ||
330 | kfree(new_t); | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | } | ||
334 | new_t->next = NULL; | ||
335 | new_t->cmd = cmd; | ||
336 | new_t->handler = handler; | ||
337 | ioctl32_insert_translation(new_t); | ||
338 | |||
339 | up_write(&ioctl32_sem); | ||
340 | return 0; | ||
341 | } | ||
342 | EXPORT_SYMBOL(register_ioctl32_conversion); | ||
343 | |||
344 | static inline int builtin_ioctl(struct ioctl_trans *t) | ||
345 | { | ||
346 | return t >= ioctl_start && t < (ioctl_start + ioctl_table_size); | ||
347 | } | ||
348 | |||
349 | /* Problem: | ||
350 | This function cannot unregister duplicate ioctls, because they are not | ||
351 | unique. | ||
352 | When they happen we need to extend the prototype to pass the handler too. */ | ||
353 | |||
354 | int unregister_ioctl32_conversion(unsigned int cmd) | ||
355 | { | ||
356 | unsigned long hash = ioctl32_hash(cmd); | ||
357 | struct ioctl_trans *t, *t1; | ||
358 | |||
359 | down_write(&ioctl32_sem); | ||
360 | |||
361 | t = ioctl32_hash_table[hash]; | ||
362 | if (!t) { | ||
363 | up_write(&ioctl32_sem); | ||
364 | return -EINVAL; | ||
365 | } | ||
366 | |||
367 | if (t->cmd == cmd) { | ||
368 | if (builtin_ioctl(t)) { | ||
369 | printk("%p tried to unregister builtin ioctl %x\n", | ||
370 | __builtin_return_address(0), cmd); | ||
371 | } else { | ||
372 | ioctl32_hash_table[hash] = t->next; | ||
373 | up_write(&ioctl32_sem); | ||
374 | kfree(t); | ||
375 | return 0; | ||
376 | } | ||
377 | } | ||
378 | while (t->next) { | ||
379 | t1 = t->next; | ||
380 | if (t1->cmd == cmd) { | ||
381 | if (builtin_ioctl(t1)) { | ||
382 | printk("%p tried to unregister builtin " | ||
383 | "ioctl %x\n", | ||
384 | __builtin_return_address(0), cmd); | ||
385 | goto out; | ||
386 | } else { | ||
387 | t->next = t1->next; | ||
388 | up_write(&ioctl32_sem); | ||
389 | kfree(t1); | ||
390 | return 0; | ||
391 | } | ||
392 | } | ||
393 | t = t1; | ||
394 | } | ||
395 | printk(KERN_ERR "Trying to free unknown 32bit ioctl handler %x\n", | ||
396 | cmd); | ||
397 | out: | ||
398 | up_write(&ioctl32_sem); | ||
399 | return -EINVAL; | ||
400 | } | ||
401 | EXPORT_SYMBOL(unregister_ioctl32_conversion); | ||
402 | |||
403 | static void compat_ioctl_error(struct file *filp, unsigned int fd, | 313 | static void compat_ioctl_error(struct file *filp, unsigned int fd, |
404 | unsigned int cmd, unsigned long arg) | 314 | unsigned int cmd, unsigned long arg) |
405 | { | 315 | { |
@@ -720,14 +630,14 @@ compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb) | |||
720 | struct compat_ncp_mount_data { | 630 | struct compat_ncp_mount_data { |
721 | compat_int_t version; | 631 | compat_int_t version; |
722 | compat_uint_t ncp_fd; | 632 | compat_uint_t ncp_fd; |
723 | compat_uid_t mounted_uid; | 633 | __compat_uid_t mounted_uid; |
724 | compat_pid_t wdog_pid; | 634 | compat_pid_t wdog_pid; |
725 | unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; | 635 | unsigned char mounted_vol[NCP_VOLNAME_LEN + 1]; |
726 | compat_uint_t time_out; | 636 | compat_uint_t time_out; |
727 | compat_uint_t retry_count; | 637 | compat_uint_t retry_count; |
728 | compat_uint_t flags; | 638 | compat_uint_t flags; |
729 | compat_uid_t uid; | 639 | __compat_uid_t uid; |
730 | compat_gid_t gid; | 640 | __compat_gid_t gid; |
731 | compat_mode_t file_mode; | 641 | compat_mode_t file_mode; |
732 | compat_mode_t dir_mode; | 642 | compat_mode_t dir_mode; |
733 | }; | 643 | }; |
@@ -784,9 +694,9 @@ static void *do_ncp_super_data_conv(void *raw_data) | |||
784 | 694 | ||
785 | struct compat_smb_mount_data { | 695 | struct compat_smb_mount_data { |
786 | compat_int_t version; | 696 | compat_int_t version; |
787 | compat_uid_t mounted_uid; | 697 | __compat_uid_t mounted_uid; |
788 | compat_uid_t uid; | 698 | __compat_uid_t uid; |
789 | compat_gid_t gid; | 699 | __compat_gid_t gid; |
790 | compat_mode_t file_mode; | 700 | compat_mode_t file_mode; |
791 | compat_mode_t dir_mode; | 701 | compat_mode_t dir_mode; |
792 | }; | 702 | }; |
@@ -1365,6 +1275,16 @@ out: | |||
1365 | } | 1275 | } |
1366 | 1276 | ||
1367 | /* | 1277 | /* |
1278 | * Exactly like fs/open.c:sys_open(), except that it doesn't set the | ||
1279 | * O_LARGEFILE flag. | ||
1280 | */ | ||
1281 | asmlinkage long | ||
1282 | compat_sys_open(const char __user *filename, int flags, int mode) | ||
1283 | { | ||
1284 | return do_sys_open(filename, flags, mode); | ||
1285 | } | ||
1286 | |||
1287 | /* | ||
1368 | * compat_count() counts the number of arguments/envelopes. It is basically | 1288 | * compat_count() counts the number of arguments/envelopes. It is basically |
1369 | * a copy of count() from fs/exec.c, except that it works with 32 bit argv | 1289 | * a copy of count() from fs/exec.c, except that it works with 32 bit argv |
1370 | * and envp pointers. | 1290 | * and envp pointers. |
@@ -1699,6 +1619,7 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp | |||
1699 | char *bits; | 1619 | char *bits; |
1700 | long timeout; | 1620 | long timeout; |
1701 | int size, max_fdset, ret = -EINVAL; | 1621 | int size, max_fdset, ret = -EINVAL; |
1622 | struct fdtable *fdt; | ||
1702 | 1623 | ||
1703 | timeout = MAX_SCHEDULE_TIMEOUT; | 1624 | timeout = MAX_SCHEDULE_TIMEOUT; |
1704 | if (tvp) { | 1625 | if (tvp) { |
@@ -1724,7 +1645,10 @@ compat_sys_select(int n, compat_ulong_t __user *inp, compat_ulong_t __user *outp | |||
1724 | goto out_nofds; | 1645 | goto out_nofds; |
1725 | 1646 | ||
1726 | /* max_fdset can increase, so grab it once to avoid race */ | 1647 | /* max_fdset can increase, so grab it once to avoid race */ |
1727 | max_fdset = current->files->max_fdset; | 1648 | rcu_read_lock(); |
1649 | fdt = files_fdtable(current->files); | ||
1650 | max_fdset = fdt->max_fdset; | ||
1651 | rcu_read_unlock(); | ||
1728 | if (n > max_fdset) | 1652 | if (n > max_fdset) |
1729 | n = max_fdset; | 1653 | n = max_fdset; |
1730 | 1654 | ||
@@ -1808,8 +1732,8 @@ struct compat_nfsctl_export { | |||
1808 | compat_dev_t ex32_dev; | 1732 | compat_dev_t ex32_dev; |
1809 | compat_ino_t ex32_ino; | 1733 | compat_ino_t ex32_ino; |
1810 | compat_int_t ex32_flags; | 1734 | compat_int_t ex32_flags; |
1811 | compat_uid_t ex32_anon_uid; | 1735 | __compat_uid_t ex32_anon_uid; |
1812 | compat_gid_t ex32_anon_gid; | 1736 | __compat_gid_t ex32_anon_gid; |
1813 | }; | 1737 | }; |
1814 | 1738 | ||
1815 | struct compat_nfsctl_fdparm { | 1739 | struct compat_nfsctl_fdparm { |