aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c84
1 files changed, 29 insertions, 55 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 0644a154672b..f6fd0a00e6cc 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -29,8 +29,6 @@
29#include <linux/vfs.h> 29#include <linux/vfs.h>
30#include <linux/ioctl.h> 30#include <linux/ioctl.h>
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/smb.h>
33#include <linux/smb_mount.h>
34#include <linux/ncp_mount.h> 32#include <linux/ncp_mount.h>
35#include <linux/nfs4_mount.h> 33#include <linux/nfs4_mount.h>
36#include <linux/syscalls.h> 34#include <linux/syscalls.h>
@@ -51,6 +49,7 @@
51#include <linux/eventpoll.h> 49#include <linux/eventpoll.h>
52#include <linux/fs_struct.h> 50#include <linux/fs_struct.h>
53#include <linux/slab.h> 51#include <linux/slab.h>
52#include <linux/pagemap.h>
54 53
55#include <asm/uaccess.h> 54#include <asm/uaccess.h>
56#include <asm/mmu_context.h> 55#include <asm/mmu_context.h>
@@ -258,7 +257,7 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
258} 257}
259 258
260/* 259/*
261 * The following statfs calls are copies of code from fs/open.c and 260 * The following statfs calls are copies of code from fs/statfs.c and
262 * should be checked against those from time to time 261 * should be checked against those from time to time
263 */ 262 */
264asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf) 263asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
@@ -321,7 +320,9 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
321 __put_user(kbuf->f_namelen, &ubuf->f_namelen) || 320 __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
322 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || 321 __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
323 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || 322 __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
324 __put_user(kbuf->f_frsize, &ubuf->f_frsize)) 323 __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
324 __put_user(kbuf->f_flags, &ubuf->f_flags) ||
325 __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
325 return -EFAULT; 326 return -EFAULT;
326 return 0; 327 return 0;
327} 328}
@@ -598,24 +599,22 @@ ssize_t compat_rw_copy_check_uvector(int type,
598 if (nr_segs > fast_segs) { 599 if (nr_segs > fast_segs) {
599 ret = -ENOMEM; 600 ret = -ENOMEM;
600 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); 601 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
601 if (iov == NULL) { 602 if (iov == NULL)
602 *ret_pointer = fast_pointer;
603 goto out; 603 goto out;
604 }
605 } 604 }
606 *ret_pointer = iov; 605 *ret_pointer = iov;
607 606
608 /* 607 /*
609 * Single unix specification: 608 * Single unix specification:
610 * We should -EINVAL if an element length is not >= 0 and fitting an 609 * We should -EINVAL if an element length is not >= 0 and fitting an
611 * ssize_t. The total length is fitting an ssize_t 610 * ssize_t.
612 * 611 *
613 * Be careful here because iov_len is a size_t not an ssize_t 612 * In Linux, the total length is limited to MAX_RW_COUNT, there is
613 * no overflow possibility.
614 */ 614 */
615 tot_len = 0; 615 tot_len = 0;
616 ret = -EINVAL; 616 ret = -EINVAL;
617 for (seg = 0; seg < nr_segs; seg++) { 617 for (seg = 0; seg < nr_segs; seg++) {
618 compat_ssize_t tmp = tot_len;
619 compat_uptr_t buf; 618 compat_uptr_t buf;
620 compat_ssize_t len; 619 compat_ssize_t len;
621 620
@@ -626,13 +625,13 @@ ssize_t compat_rw_copy_check_uvector(int type,
626 } 625 }
627 if (len < 0) /* size_t not fitting in compat_ssize_t .. */ 626 if (len < 0) /* size_t not fitting in compat_ssize_t .. */
628 goto out; 627 goto out;
629 tot_len += len;
630 if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
631 goto out;
632 if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) { 628 if (!access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
633 ret = -EFAULT; 629 ret = -EFAULT;
634 goto out; 630 goto out;
635 } 631 }
632 if (len > MAX_RW_COUNT - tot_len)
633 len = MAX_RW_COUNT - tot_len;
634 tot_len += len;
636 iov->iov_base = compat_ptr(buf); 635 iov->iov_base = compat_ptr(buf);
637 iov->iov_len = (compat_size_t) len; 636 iov->iov_len = (compat_size_t) len;
638 uvector++; 637 uvector++;
@@ -745,30 +744,6 @@ static void *do_ncp_super_data_conv(void *raw_data)
745 return raw_data; 744 return raw_data;
746} 745}
747 746
748struct compat_smb_mount_data {
749 compat_int_t version;
750 __compat_uid_t mounted_uid;
751 __compat_uid_t uid;
752 __compat_gid_t gid;
753 compat_mode_t file_mode;
754 compat_mode_t dir_mode;
755};
756
757static void *do_smb_super_data_conv(void *raw_data)
758{
759 struct smb_mount_data *s = raw_data;
760 struct compat_smb_mount_data *c_s = raw_data;
761
762 if (c_s->version != SMB_MOUNT_OLDVERSION)
763 goto out;
764 s->dir_mode = c_s->dir_mode;
765 s->file_mode = c_s->file_mode;
766 s->gid = c_s->gid;
767 s->uid = c_s->uid;
768 s->mounted_uid = c_s->mounted_uid;
769 out:
770 return raw_data;
771}
772 747
773struct compat_nfs_string { 748struct compat_nfs_string {
774 compat_uint_t len; 749 compat_uint_t len;
@@ -835,7 +810,6 @@ static int do_nfs4_super_data_conv(void *raw_data)
835 return 0; 810 return 0;
836} 811}
837 812
838#define SMBFS_NAME "smbfs"
839#define NCPFS_NAME "ncpfs" 813#define NCPFS_NAME "ncpfs"
840#define NFS4_NAME "nfs4" 814#define NFS4_NAME "nfs4"
841 815
@@ -870,9 +844,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
870 retval = -EINVAL; 844 retval = -EINVAL;
871 845
872 if (kernel_type && data_page) { 846 if (kernel_type && data_page) {
873 if (!strcmp(kernel_type, SMBFS_NAME)) { 847 if (!strcmp(kernel_type, NCPFS_NAME)) {
874 do_smb_super_data_conv((void *)data_page);
875 } else if (!strcmp(kernel_type, NCPFS_NAME)) {
876 do_ncp_super_data_conv((void *)data_page); 848 do_ncp_super_data_conv((void *)data_page);
877 } else if (!strcmp(kernel_type, NFS4_NAME)) { 849 } else if (!strcmp(kernel_type, NFS4_NAME)) {
878 if (do_nfs4_super_data_conv((void *) data_page)) 850 if (do_nfs4_super_data_conv((void *) data_page))
@@ -1378,6 +1350,10 @@ static int compat_count(compat_uptr_t __user *argv, int max)
1378 argv++; 1350 argv++;
1379 if (i++ >= max) 1351 if (i++ >= max)
1380 return -E2BIG; 1352 return -E2BIG;
1353
1354 if (fatal_signal_pending(current))
1355 return -ERESTARTNOHAND;
1356 cond_resched();
1381 } 1357 }
1382 } 1358 }
1383 return i; 1359 return i;
@@ -1419,6 +1395,12 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv,
1419 while (len > 0) { 1395 while (len > 0) {
1420 int offset, bytes_to_copy; 1396 int offset, bytes_to_copy;
1421 1397
1398 if (fatal_signal_pending(current)) {
1399 ret = -ERESTARTNOHAND;
1400 goto out;
1401 }
1402 cond_resched();
1403
1422 offset = pos % PAGE_SIZE; 1404 offset = pos % PAGE_SIZE;
1423 if (offset == 0) 1405 if (offset == 0)
1424 offset = PAGE_SIZE; 1406 offset = PAGE_SIZE;
@@ -1435,18 +1417,8 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv,
1435 if (!kmapped_page || kpos != (pos & PAGE_MASK)) { 1417 if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
1436 struct page *page; 1418 struct page *page;
1437 1419
1438#ifdef CONFIG_STACK_GROWSUP 1420 page = get_arg_page(bprm, pos, 1);
1439 ret = expand_stack_downwards(bprm->vma, pos); 1421 if (!page) {
1440 if (ret < 0) {
1441 /* We've exceed the stack rlimit. */
1442 ret = -E2BIG;
1443 goto out;
1444 }
1445#endif
1446 ret = get_user_pages(current, bprm->mm, pos,
1447 1, 1, 1, &page, NULL);
1448 if (ret <= 0) {
1449 /* We've exceed the stack rlimit. */
1450 ret = -E2BIG; 1422 ret = -E2BIG;
1451 goto out; 1423 goto out;
1452 } 1424 }
@@ -1567,8 +1539,10 @@ int compat_do_execve(char * filename,
1567 return retval; 1539 return retval;
1568 1540
1569out: 1541out:
1570 if (bprm->mm) 1542 if (bprm->mm) {
1543 acct_arg_size(bprm, 0);
1571 mmput(bprm->mm); 1544 mmput(bprm->mm);
1545 }
1572 1546
1573out_file: 1547out_file:
1574 if (bprm->file) { 1548 if (bprm->file) {
@@ -1963,7 +1937,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1963} 1937}
1964#endif /* HAVE_SET_RESTORE_SIGMASK */ 1938#endif /* HAVE_SET_RESTORE_SIGMASK */
1965 1939
1966#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) 1940#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED)
1967/* Stuff for NFS server syscalls... */ 1941/* Stuff for NFS server syscalls... */
1968struct compat_nfsctl_svc { 1942struct compat_nfsctl_svc {
1969 u16 svc32_port; 1943 u16 svc32_port;