Linux Audio

Check our new training course

Loading...
  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}