at v5.2 3.3 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/fs/compat.c 4 * 5 * Kernel compatibililty routines for e.g. 32 bit syscall support 6 * on 64 bit kernels. 7 * 8 * Copyright (C) 2002 Stephen Rothwell, IBM Corporation 9 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) 10 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) 11 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs 12 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) 13 */ 14 15#include <linux/compat.h> 16#include <linux/nfs4_mount.h> 17#include <linux/syscalls.h> 18#include <linux/slab.h> 19#include <linux/uaccess.h> 20#include "internal.h" 21 22struct compat_nfs_string { 23 compat_uint_t len; 24 compat_uptr_t data; 25}; 26 27static inline void compat_nfs_string(struct nfs_string *dst, 28 struct compat_nfs_string *src) 29{ 30 dst->data = compat_ptr(src->data); 31 dst->len = src->len; 32} 33 34struct compat_nfs4_mount_data_v1 { 35 compat_int_t version; 36 compat_int_t flags; 37 compat_int_t rsize; 38 compat_int_t wsize; 39 compat_int_t timeo; 40 compat_int_t retrans; 41 compat_int_t acregmin; 42 compat_int_t acregmax; 43 compat_int_t acdirmin; 44 compat_int_t acdirmax; 45 struct compat_nfs_string client_addr; 46 struct compat_nfs_string mnt_path; 47 struct compat_nfs_string hostname; 48 compat_uint_t host_addrlen; 49 compat_uptr_t host_addr; 50 compat_int_t proto; 51 compat_int_t auth_flavourlen; 52 compat_uptr_t auth_flavours; 53}; 54 55static int do_nfs4_super_data_conv(void *raw_data) 56{ 57 int version = *(compat_uint_t *) raw_data; 58 59 if (version == 1) { 60 struct compat_nfs4_mount_data_v1 *raw = raw_data; 61 struct nfs4_mount_data *real = raw_data; 62 63 /* copy the fields backwards */ 64 real->auth_flavours = compat_ptr(raw->auth_flavours); 65 real->auth_flavourlen = raw->auth_flavourlen; 66 real->proto = raw->proto; 67 real->host_addr = compat_ptr(raw->host_addr); 68 real->host_addrlen = raw->host_addrlen; 69 compat_nfs_string(&real->hostname, &raw->hostname); 70 compat_nfs_string(&real->mnt_path, &raw->mnt_path); 71 compat_nfs_string(&real->client_addr, &raw->client_addr); 72 real->acdirmax = raw->acdirmax; 73 real->acdirmin = raw->acdirmin; 74 real->acregmax = raw->acregmax; 75 real->acregmin = raw->acregmin; 76 real->retrans = raw->retrans; 77 real->timeo = raw->timeo; 78 real->wsize = raw->wsize; 79 real->rsize = raw->rsize; 80 real->flags = raw->flags; 81 real->version = raw->version; 82 } 83 84 return 0; 85} 86 87#define NFS4_NAME "nfs4" 88 89COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name, 90 const char __user *, dir_name, 91 const char __user *, type, compat_ulong_t, flags, 92 const void __user *, data) 93{ 94 char *kernel_type; 95 void *options; 96 char *kernel_dev; 97 int retval; 98 99 kernel_type = copy_mount_string(type); 100 retval = PTR_ERR(kernel_type); 101 if (IS_ERR(kernel_type)) 102 goto out; 103 104 kernel_dev = copy_mount_string(dev_name); 105 retval = PTR_ERR(kernel_dev); 106 if (IS_ERR(kernel_dev)) 107 goto out1; 108 109 options = copy_mount_options(data); 110 retval = PTR_ERR(options); 111 if (IS_ERR(options)) 112 goto out2; 113 114 if (kernel_type && options) { 115 if (!strcmp(kernel_type, NFS4_NAME)) { 116 retval = -EINVAL; 117 if (do_nfs4_super_data_conv(options)) 118 goto out3; 119 } 120 } 121 122 retval = do_mount(kernel_dev, dir_name, kernel_type, flags, options); 123 124 out3: 125 kfree(options); 126 out2: 127 kfree(kernel_dev); 128 out1: 129 kfree(kernel_type); 130 out: 131 return retval; 132}