Blame view

fs/compat.c 5.09 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
  /*
   *  linux/fs/compat.c
   *
   *  Kernel compatibililty routines for e.g. 32 bit syscall support
   *  on 64 bit kernels.
   *
   *  Copyright (C) 2002       Stephen Rothwell, IBM Corporation
   *  Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
   *  Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
   *  Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
a2531293d   Pavel Machek   update email address
11
   *  Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License version 2 as
   *  published by the Free Software Foundation.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/ncp_mount.h>
9a9947bf7   David Howells   [PATCH] Add 32-bi...
19
  #include <linux/nfs4_mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <linux/syscalls.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
22
  #include <linux/uaccess.h>
07f3f05c1   David Howells   [PATCH] BLOCK: Mo...
23
  #include "internal.h"
9f72949f6   David Woodhouse   [PATCH] Add psele...
24

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
  struct compat_ncp_mount_data {
  	compat_int_t version;
  	compat_uint_t ncp_fd;
202e5979a   Stephen Rothwell   [PATCH] compat: b...
28
  	__compat_uid_t mounted_uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
30
31
32
33
  	compat_pid_t wdog_pid;
  	unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
  	compat_uint_t time_out;
  	compat_uint_t retry_count;
  	compat_uint_t flags;
202e5979a   Stephen Rothwell   [PATCH] compat: b...
34
35
  	__compat_uid_t uid;
  	__compat_gid_t gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  	compat_mode_t file_mode;
  	compat_mode_t dir_mode;
  };
  
  struct compat_ncp_mount_data_v4 {
  	compat_int_t version;
  	compat_ulong_t flags;
  	compat_ulong_t mounted_uid;
  	compat_long_t wdog_pid;
  	compat_uint_t ncp_fd;
  	compat_uint_t time_out;
  	compat_uint_t retry_count;
  	compat_ulong_t uid;
  	compat_ulong_t gid;
  	compat_ulong_t file_mode;
  	compat_ulong_t dir_mode;
  };
  
  static void *do_ncp_super_data_conv(void *raw_data)
  {
  	int version = *(unsigned int *)raw_data;
  
  	if (version == 3) {
  		struct compat_ncp_mount_data *c_n = raw_data;
  		struct ncp_mount_data *n = raw_data;
  
  		n->dir_mode = c_n->dir_mode;
  		n->file_mode = c_n->file_mode;
  		n->gid = c_n->gid;
  		n->uid = c_n->uid;
  		memmove (n->mounted_vol, c_n->mounted_vol, (sizeof (c_n->mounted_vol) + 3 * sizeof (unsigned int)));
  		n->wdog_pid = c_n->wdog_pid;
  		n->mounted_uid = c_n->mounted_uid;
  	} else if (version == 4) {
  		struct compat_ncp_mount_data_v4 *c_n = raw_data;
  		struct ncp_mount_data_v4 *n = raw_data;
  
  		n->dir_mode = c_n->dir_mode;
  		n->file_mode = c_n->file_mode;
  		n->gid = c_n->gid;
  		n->uid = c_n->uid;
  		n->retry_count = c_n->retry_count;
  		n->time_out = c_n->time_out;
  		n->ncp_fd = c_n->ncp_fd;
  		n->wdog_pid = c_n->wdog_pid;
  		n->mounted_uid = c_n->mounted_uid;
  		n->flags = c_n->flags;
  	} else if (version != 5) {
  		return NULL;
  	}
  
  	return raw_data;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89

9a9947bf7   David Howells   [PATCH] Add 32-bi...
90
91
  struct compat_nfs_string {
  	compat_uint_t len;
5fc3e624a   David Howells   [PATCH] NFS4: Don...
92
  	compat_uptr_t data;
9a9947bf7   David Howells   [PATCH] Add 32-bi...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  };
  
  static inline void compat_nfs_string(struct nfs_string *dst,
  				     struct compat_nfs_string *src)
  {
  	dst->data = compat_ptr(src->data);
  	dst->len = src->len;
  }
  
  struct compat_nfs4_mount_data_v1 {
  	compat_int_t version;
  	compat_int_t flags;
  	compat_int_t rsize;
  	compat_int_t wsize;
  	compat_int_t timeo;
  	compat_int_t retrans;
  	compat_int_t acregmin;
  	compat_int_t acregmax;
  	compat_int_t acdirmin;
  	compat_int_t acdirmax;
  	struct compat_nfs_string client_addr;
  	struct compat_nfs_string mnt_path;
  	struct compat_nfs_string hostname;
  	compat_uint_t host_addrlen;
5fc3e624a   David Howells   [PATCH] NFS4: Don...
117
  	compat_uptr_t host_addr;
9a9947bf7   David Howells   [PATCH] Add 32-bi...
118
119
  	compat_int_t proto;
  	compat_int_t auth_flavourlen;
5fc3e624a   David Howells   [PATCH] NFS4: Don...
120
  	compat_uptr_t auth_flavours;
9a9947bf7   David Howells   [PATCH] Add 32-bi...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  };
  
  static int do_nfs4_super_data_conv(void *raw_data)
  {
  	int version = *(compat_uint_t *) raw_data;
  
  	if (version == 1) {
  		struct compat_nfs4_mount_data_v1 *raw = raw_data;
  		struct nfs4_mount_data *real = raw_data;
  
  		/* copy the fields backwards */
  		real->auth_flavours = compat_ptr(raw->auth_flavours);
  		real->auth_flavourlen = raw->auth_flavourlen;
  		real->proto = raw->proto;
  		real->host_addr = compat_ptr(raw->host_addr);
  		real->host_addrlen = raw->host_addrlen;
  		compat_nfs_string(&real->hostname, &raw->hostname);
  		compat_nfs_string(&real->mnt_path, &raw->mnt_path);
  		compat_nfs_string(&real->client_addr, &raw->client_addr);
  		real->acdirmax = raw->acdirmax;
  		real->acdirmin = raw->acdirmin;
  		real->acregmax = raw->acregmax;
  		real->acregmin = raw->acregmin;
  		real->retrans = raw->retrans;
  		real->timeo = raw->timeo;
  		real->wsize = raw->wsize;
  		real->rsize = raw->rsize;
  		real->flags = raw->flags;
  		real->version = raw->version;
  	}
9a9947bf7   David Howells   [PATCH] Add 32-bi...
151
152
153
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
  #define NCPFS_NAME      "ncpfs"
9a9947bf7   David Howells   [PATCH] Add 32-bi...
155
  #define NFS4_NAME	"nfs4"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156

932602e23   Heiko Carstens   fs/compat: conver...
157
158
159
160
  COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
  		       const char __user *, dir_name,
  		       const char __user *, type, compat_ulong_t, flags,
  		       const void __user *, data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  {
eca6f534e   Vegard Nossum   fs: fix overflow ...
162
  	char *kernel_type;
b40ef8696   Al Viro   saner calling con...
163
  	void *options;
eca6f534e   Vegard Nossum   fs: fix overflow ...
164
  	char *kernel_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  	int retval;
b8850d1fa   Tim Gardner   fs: namespace: su...
166
167
168
  	kernel_type = copy_mount_string(type);
  	retval = PTR_ERR(kernel_type);
  	if (IS_ERR(kernel_type))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  		goto out;
b8850d1fa   Tim Gardner   fs: namespace: su...
170
171
172
  	kernel_dev = copy_mount_string(dev_name);
  	retval = PTR_ERR(kernel_dev);
  	if (IS_ERR(kernel_dev))
5e6123f34   Seunghun Lee   vfs: move getname...
173
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174

b40ef8696   Al Viro   saner calling con...
175
176
177
  	options = copy_mount_options(data);
  	retval = PTR_ERR(options);
  	if (IS_ERR(options))
5e6123f34   Seunghun Lee   vfs: move getname...
178
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179

b40ef8696   Al Viro   saner calling con...
180
  	if (kernel_type && options) {
2116b7a47   Arnd Bergmann   smbfs: move to dr...
181
  		if (!strcmp(kernel_type, NCPFS_NAME)) {
b40ef8696   Al Viro   saner calling con...
182
  			do_ncp_super_data_conv(options);
eca6f534e   Vegard Nossum   fs: fix overflow ...
183
  		} else if (!strcmp(kernel_type, NFS4_NAME)) {
b40ef8696   Al Viro   saner calling con...
184
185
  			retval = -EINVAL;
  			if (do_nfs4_super_data_conv(options))
5e6123f34   Seunghun Lee   vfs: move getname...
186
  				goto out3;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
  		}
  	}
b40ef8696   Al Viro   saner calling con...
189
  	retval = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
   out3:
b40ef8696   Al Viro   saner calling con...
192
  	kfree(options);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
   out2:
5e6123f34   Seunghun Lee   vfs: move getname...
194
  	kfree(kernel_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
   out1:
eca6f534e   Vegard Nossum   fs: fix overflow ...
196
  	kfree(kernel_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
198
199
   out:
  	return retval;
  }