aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2005-04-18 13:54:51 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-18 13:54:51 -0400
commit9a9947bf7a3a14d2107cb9a27279fc8f463370a9 (patch)
tree7e90be835df68f4821ffa7264eec7a6c5b03f1d3 /fs/compat.c
parent219f0817038cabc722968e914490adf6b686499e (diff)
[PATCH] Add 32-bit compatibility for NFSv4 mount
This adds 32-bit compatibility for mounting an NFSv4 mount on a 64-bit kernel (such as happens with PPC64). The problem is that the mount data for the NFS4 mount process includes auxilliary data pointers, probably because the NFS4 mount data may conceivably exceed PAGE_SIZE in size - thus breaking against the hard limit imposed by sys_mount(). Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/fs/compat.c b/fs/compat.c
index a912bdf691cf..67c0b94d1148 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -31,6 +31,7 @@
31#include <linux/smb.h> 31#include <linux/smb.h>
32#include <linux/smb_mount.h> 32#include <linux/smb_mount.h>
33#include <linux/ncp_mount.h> 33#include <linux/ncp_mount.h>
34#include <linux/nfs4_mount.h>
34#include <linux/smp_lock.h> 35#include <linux/smp_lock.h>
35#include <linux/syscalls.h> 36#include <linux/syscalls.h>
36#include <linux/ctype.h> 37#include <linux/ctype.h>
@@ -806,10 +807,79 @@ static void *do_smb_super_data_conv(void *raw_data)
806 return raw_data; 807 return raw_data;
807} 808}
808 809
810struct compat_nfs_string {
811 compat_uint_t len;
812 compat_uptr_t __user data;
813};
814
815static inline void compat_nfs_string(struct nfs_string *dst,
816 struct compat_nfs_string *src)
817{
818 dst->data = compat_ptr(src->data);
819 dst->len = src->len;
820}
821
822struct compat_nfs4_mount_data_v1 {
823 compat_int_t version;
824 compat_int_t flags;
825 compat_int_t rsize;
826 compat_int_t wsize;
827 compat_int_t timeo;
828 compat_int_t retrans;
829 compat_int_t acregmin;
830 compat_int_t acregmax;
831 compat_int_t acdirmin;
832 compat_int_t acdirmax;
833 struct compat_nfs_string client_addr;
834 struct compat_nfs_string mnt_path;
835 struct compat_nfs_string hostname;
836 compat_uint_t host_addrlen;
837 compat_uptr_t __user host_addr;
838 compat_int_t proto;
839 compat_int_t auth_flavourlen;
840 compat_uptr_t __user auth_flavours;
841};
842
843static int do_nfs4_super_data_conv(void *raw_data)
844{
845 int version = *(compat_uint_t *) raw_data;
846
847 if (version == 1) {
848 struct compat_nfs4_mount_data_v1 *raw = raw_data;
849 struct nfs4_mount_data *real = raw_data;
850
851 /* copy the fields backwards */
852 real->auth_flavours = compat_ptr(raw->auth_flavours);
853 real->auth_flavourlen = raw->auth_flavourlen;
854 real->proto = raw->proto;
855 real->host_addr = compat_ptr(raw->host_addr);
856 real->host_addrlen = raw->host_addrlen;
857 compat_nfs_string(&real->hostname, &raw->hostname);
858 compat_nfs_string(&real->mnt_path, &raw->mnt_path);
859 compat_nfs_string(&real->client_addr, &raw->client_addr);
860 real->acdirmax = raw->acdirmax;
861 real->acdirmin = raw->acdirmin;
862 real->acregmax = raw->acregmax;
863 real->acregmin = raw->acregmin;
864 real->retrans = raw->retrans;
865 real->timeo = raw->timeo;
866 real->wsize = raw->wsize;
867 real->rsize = raw->rsize;
868 real->flags = raw->flags;
869 real->version = raw->version;
870 }
871 else {
872 return -EINVAL;
873 }
874
875 return 0;
876}
877
809extern int copy_mount_options (const void __user *, unsigned long *); 878extern int copy_mount_options (const void __user *, unsigned long *);
810 879
811#define SMBFS_NAME "smbfs" 880#define SMBFS_NAME "smbfs"
812#define NCPFS_NAME "ncpfs" 881#define NCPFS_NAME "ncpfs"
882#define NFS4_NAME "nfs4"
813 883
814asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name, 884asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
815 char __user * type, unsigned long flags, 885 char __user * type, unsigned long flags,
@@ -845,6 +915,9 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
845 do_smb_super_data_conv((void *)data_page); 915 do_smb_super_data_conv((void *)data_page);
846 } else if (!strcmp((char *)type_page, NCPFS_NAME)) { 916 } else if (!strcmp((char *)type_page, NCPFS_NAME)) {
847 do_ncp_super_data_conv((void *)data_page); 917 do_ncp_super_data_conv((void *)data_page);
918 } else if (!strcmp((char *)type_page, NFS4_NAME)) {
919 if (do_nfs4_super_data_conv((void *) data_page))
920 goto out4;
848 } 921 }
849 } 922 }
850 923
@@ -853,6 +926,7 @@ asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
853 flags, (void*)data_page); 926 flags, (void*)data_page);
854 unlock_kernel(); 927 unlock_kernel();
855 928
929 out4:
856 free_page(data_page); 930 free_page(data_page);
857 out3: 931 out3:
858 free_page(dev_page); 932 free_page(dev_page);