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