Blame view

fs/open.c 26.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
  /*
   *  linux/fs/open.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   */
  
  #include <linux/string.h>
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
  #include <linux/file.h>
9f3acc314   Al Viro   [PATCH] split lin...
10
  #include <linux/fdtable.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
  #include <linux/quotaops.h>
0eeca2830   Robert Love   [PATCH] inotify
12
  #include <linux/fsnotify.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
16
17
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/tty.h>
  #include <linux/namei.h>
  #include <linux/backing-dev.h>
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
18
  #include <linux/capability.h>
086f7316f   Andrew G. Morgan   security: filesys...
19
  #include <linux/securebits.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
  #include <linux/security.h>
  #include <linux/mount.h>
  #include <linux/vfs.h>
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
23
  #include <linux/fcntl.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  #include <asm/uaccess.h>
  #include <linux/fs.h>
ef3daeda7   Yoav Zach   [PATCH] Don't for...
26
  #include <linux/personality.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
  #include <linux/pagemap.h>
  #include <linux/syscalls.h>
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
29
  #include <linux/rcupdate.h>
73241ccca   Amy Griffis   [PATCH] Collect m...
30
  #include <linux/audit.h>
97ac73506   Amit Arora   sys_fallocate() i...
31
  #include <linux/falloc.h>
5ad4e53bd   Al Viro   Get rid of indire...
32
  #include <linux/fs_struct.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

726c33422   David Howells   [PATCH] VFS: Perm...
34
  int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
  {
  	int retval = -ENODEV;
726c33422   David Howells   [PATCH] VFS: Perm...
37
  	if (dentry) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
  		retval = -ENOSYS;
726c33422   David Howells   [PATCH] VFS: Perm...
39
  		if (dentry->d_sb->s_op->statfs) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  			memset(buf, 0, sizeof(*buf));
726c33422   David Howells   [PATCH] VFS: Perm...
41
  			retval = security_sb_statfs(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  			if (retval)
  				return retval;
726c33422   David Howells   [PATCH] VFS: Perm...
44
  			retval = dentry->d_sb->s_op->statfs(dentry, buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
51
52
  			if (retval == 0 && buf->f_frsize == 0)
  				buf->f_frsize = buf->f_bsize;
  		}
  	}
  	return retval;
  }
  
  EXPORT_SYMBOL(vfs_statfs);
726c33422   David Howells   [PATCH] VFS: Perm...
53
  static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
  {
  	struct kstatfs st;
  	int retval;
726c33422   David Howells   [PATCH] VFS: Perm...
57
  	retval = vfs_statfs(dentry, &st);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
  	if (retval)
  		return retval;
  
  	if (sizeof(*buf) == sizeof(st))
  		memcpy(buf, &st, sizeof(st));
  	else {
  		if (sizeof buf->f_blocks == 4) {
f4a67ccee   Jon Tollefson   fs: check for sta...
65
66
  			if ((st.f_blocks | st.f_bfree | st.f_bavail |
  			     st.f_bsize | st.f_frsize) &
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  			    0xffffffff00000000ULL)
  				return -EOVERFLOW;
  			/*
  			 * f_files and f_ffree may be -1; it's okay to stuff
  			 * that into 32 bits
  			 */
  			if (st.f_files != -1 &&
  			    (st.f_files & 0xffffffff00000000ULL))
  				return -EOVERFLOW;
  			if (st.f_ffree != -1 &&
  			    (st.f_ffree & 0xffffffff00000000ULL))
  				return -EOVERFLOW;
  		}
  
  		buf->f_type = st.f_type;
  		buf->f_bsize = st.f_bsize;
  		buf->f_blocks = st.f_blocks;
  		buf->f_bfree = st.f_bfree;
  		buf->f_bavail = st.f_bavail;
  		buf->f_files = st.f_files;
  		buf->f_ffree = st.f_ffree;
  		buf->f_fsid = st.f_fsid;
  		buf->f_namelen = st.f_namelen;
  		buf->f_frsize = st.f_frsize;
  		memset(buf->f_spare, 0, sizeof(buf->f_spare));
  	}
  	return 0;
  }
726c33422   David Howells   [PATCH] VFS: Perm...
95
  static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
  {
  	struct kstatfs st;
  	int retval;
726c33422   David Howells   [PATCH] VFS: Perm...
99
  	retval = vfs_statfs(dentry, &st);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  	if (retval)
  		return retval;
  
  	if (sizeof(*buf) == sizeof(st))
  		memcpy(buf, &st, sizeof(st));
  	else {
  		buf->f_type = st.f_type;
  		buf->f_bsize = st.f_bsize;
  		buf->f_blocks = st.f_blocks;
  		buf->f_bfree = st.f_bfree;
  		buf->f_bavail = st.f_bavail;
  		buf->f_files = st.f_files;
  		buf->f_ffree = st.f_ffree;
  		buf->f_fsid = st.f_fsid;
  		buf->f_namelen = st.f_namelen;
  		buf->f_frsize = st.f_frsize;
  		memset(buf->f_spare, 0, sizeof(buf->f_spare));
  	}
  	return 0;
  }
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
120
  SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
122
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
124
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
  	if (!error) {
  		struct statfs tmp;
2d8f30380   Al Viro   [PATCH] sanitize ...
127
  		error = vfs_statfs_native(path.dentry, &tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
  		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  			error = -EFAULT;
2d8f30380   Al Viro   [PATCH] sanitize ...
130
  		path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  	}
  	return error;
  }
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
134
  SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
136
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
  	long error;
  
  	if (sz != sizeof(*buf))
  		return -EINVAL;
2d8f30380   Al Viro   [PATCH] sanitize ...
141
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
  	if (!error) {
  		struct statfs64 tmp;
2d8f30380   Al Viro   [PATCH] sanitize ...
144
  		error = vfs_statfs64(path.dentry, &tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  			error = -EFAULT;
2d8f30380   Al Viro   [PATCH] sanitize ...
147
  		path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
  	}
  	return error;
  }
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
151
  SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
158
159
160
  {
  	struct file * file;
  	struct statfs tmp;
  	int error;
  
  	error = -EBADF;
  	file = fget(fd);
  	if (!file)
  		goto out;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
161
  	error = vfs_statfs_native(file->f_path.dentry, &tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
165
166
167
  	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  		error = -EFAULT;
  	fput(file);
  out:
  	return error;
  }
257ac264d   Heiko Carstens   [CVE-2009-0029] S...
168
  SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
171
172
173
174
175
176
177
178
179
180
  {
  	struct file * file;
  	struct statfs64 tmp;
  	int error;
  
  	if (sz != sizeof(*buf))
  		return -EINVAL;
  
  	error = -EBADF;
  	file = fget(fd);
  	if (!file)
  		goto out;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
181
  	error = vfs_statfs64(file->f_path.dentry, &tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
184
185
186
187
  	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
  		error = -EFAULT;
  	fput(file);
  out:
  	return error;
  }
4a30131e7   NeilBrown   [PATCH] Fix some ...
188
189
  int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
  	struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
193
194
195
196
197
198
  {
  	int err;
  	struct iattr newattrs;
  
  	/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
  	if (length < 0)
  		return -EINVAL;
  
  	newattrs.ia_size = length;
4a30131e7   NeilBrown   [PATCH] Fix some ...
199
  	newattrs.ia_valid = ATTR_SIZE | time_attrs;
cc4e69dee   Miklos Szeredi   [PATCH] VFS: pass...
200
201
202
203
  	if (filp) {
  		newattrs.ia_file = filp;
  		newattrs.ia_valid |= ATTR_FILE;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204

7b82dc0e6   Linus Torvalds   Remove suid/sgid ...
205
206
  	/* Remove suid/sgid on truncate too */
  	newattrs.ia_valid |= should_remove_suid(dentry);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
207
  	mutex_lock(&dentry->d_inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  	err = notify_change(dentry, &newattrs);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
209
  	mutex_unlock(&dentry->d_inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
  	return err;
  }
2d8f30380   Al Viro   [PATCH] sanitize ...
212
  static long do_sys_truncate(const char __user *pathname, loff_t length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
214
215
  	struct path path;
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
  	int error;
  
  	error = -EINVAL;
  	if (length < 0)	/* sorry, but loff_t says... */
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
221
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
224
  	inode = path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
229
230
231
232
233
  
  	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
  	error = -EISDIR;
  	if (S_ISDIR(inode->i_mode))
  		goto dput_and_out;
  
  	error = -EINVAL;
  	if (!S_ISREG(inode->i_mode))
  		goto dput_and_out;
2d8f30380   Al Viro   [PATCH] sanitize ...
234
  	error = mnt_want_write(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
  	if (error)
  		goto dput_and_out;
256984a83   Al Viro   [PATCH] preparati...
237
  	error = inode_permission(inode, MAY_WRITE);
9ac9b8474   Dave Hansen   [PATCH] r/o bind ...
238
239
  	if (error)
  		goto mnt_drop_write_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
  
  	error = -EPERM;
c82e42da8   Miklos Szeredi   [patch 1/5] vfs: ...
242
  	if (IS_APPEND(inode))
9ac9b8474   Dave Hansen   [PATCH] r/o bind ...
243
  		goto mnt_drop_write_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244

9700382c3   david m. richter   VFS: fix a race i...
245
  	error = get_write_access(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  	if (error)
9ac9b8474   Dave Hansen   [PATCH] r/o bind ...
247
  		goto mnt_drop_write_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248

9700382c3   david m. richter   VFS: fix a race i...
249
250
251
252
253
  	/*
  	 * Make sure that there are no leases.  get_write_access() protects
  	 * against the truncate racing with a lease-granting setlease().
  	 */
  	error = break_lease(inode, FMODE_WRITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  	if (error)
9700382c3   david m. richter   VFS: fix a race i...
255
  		goto put_write_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
  
  	error = locks_verify_truncate(inode, NULL, length);
be6d3e56a   Kentaro Takeda   introduce new LSM...
258
259
  	if (!error)
  		error = security_path_truncate(&path, length, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
  	if (!error) {
9e3509e27   Jan Kara   vfs: Use lowercas...
261
  		vfs_dq_init(inode);
2d8f30380   Al Viro   [PATCH] sanitize ...
262
  		error = do_truncate(path.dentry, length, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264

9700382c3   david m. richter   VFS: fix a race i...
265
266
  put_write_and_out:
  	put_write_access(inode);
9ac9b8474   Dave Hansen   [PATCH] r/o bind ...
267
  mnt_drop_write_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
268
  	mnt_drop_write(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  dput_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
270
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
  out:
  	return error;
  }
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
274
  SYSCALL_DEFINE2(truncate, const char __user *, path, unsigned long, length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
276
277
278
  {
  	/* on 32-bit boxen it will cut the range 2^31--2^32-1 off */
  	return do_sys_truncate(path, (long)length);
  }
b01ec0ef6   Matt Mackall   [PATCH] tiny: Uni...
279
  static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  {
  	struct inode * inode;
  	struct dentry *dentry;
  	struct file * file;
  	int error;
  
  	error = -EINVAL;
  	if (length < 0)
  		goto out;
  	error = -EBADF;
  	file = fget(fd);
  	if (!file)
  		goto out;
  
  	/* explicitly opened as large or we are on 64-bit box */
  	if (file->f_flags & O_LARGEFILE)
  		small = 0;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
297
  	dentry = file->f_path.dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  	inode = dentry->d_inode;
  	error = -EINVAL;
  	if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
  		goto out_putf;
  
  	error = -EINVAL;
  	/* Cannot ftruncate over 2^31 bytes without large file support */
  	if (small && length > MAX_NON_LFS)
  		goto out_putf;
  
  	error = -EPERM;
  	if (IS_APPEND(inode))
  		goto out_putf;
  
  	error = locks_verify_truncate(inode, file, length);
  	if (!error)
be6d3e56a   Kentaro Takeda   introduce new LSM...
314
315
316
  		error = security_path_truncate(&file->f_path, length,
  					       ATTR_MTIME|ATTR_CTIME);
  	if (!error)
6e656be89   Peter Staubach   [PATCH] ftruncate...
317
  		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
321
322
  out_putf:
  	fput(file);
  out:
  	return error;
  }
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
323
  SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
  {
0a489cb3b   Linus Torvalds   x86: don't allow ...
325
  	long ret = do_sys_ftruncate(fd, length, 1);
385910f2b   Linus Torvalds   x86: be careful a...
326
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
327
  	asmlinkage_protect(2, ret, fd, length);
0a489cb3b   Linus Torvalds   x86: don't allow ...
328
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
332
  }
  
  /* LFS versions of truncate are only needed on 32 bit machines */
  #if BITS_PER_LONG == 32
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
333
  SYSCALL_DEFINE(truncate64)(const char __user * path, loff_t length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
  {
  	return do_sys_truncate(path, length);
  }
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
337
338
339
340
341
342
343
  #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
  asmlinkage long SyS_truncate64(long path, loff_t length)
  {
  	return SYSC_truncate64((const char __user *) path, length);
  }
  SYSCALL_ALIAS(sys_truncate64, SyS_truncate64);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
344

6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
345
  SYSCALL_DEFINE(ftruncate64)(unsigned int fd, loff_t length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  {
0a489cb3b   Linus Torvalds   x86: don't allow ...
347
  	long ret = do_sys_ftruncate(fd, length, 0);
385910f2b   Linus Torvalds   x86: be careful a...
348
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
349
  	asmlinkage_protect(2, ret, fd, length);
0a489cb3b   Linus Torvalds   x86: don't allow ...
350
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  }
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
352
353
354
355
356
357
  #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
  asmlinkage long SyS_ftruncate64(long fd, loff_t length)
  {
  	return SYSC_ftruncate64((unsigned int) fd, length);
  }
  SYSCALL_ALIAS(sys_ftruncate64, SyS_ftruncate64);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  #endif
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
359
  #endif /* BITS_PER_LONG == 32 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360

6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
361
  SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len)
97ac73506   Amit Arora   sys_fallocate() i...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  {
  	struct file *file;
  	struct inode *inode;
  	long ret = -EINVAL;
  
  	if (offset < 0 || len <= 0)
  		goto out;
  
  	/* Return error if mode is not supported */
  	ret = -EOPNOTSUPP;
  	if (mode && !(mode & FALLOC_FL_KEEP_SIZE))
  		goto out;
  
  	ret = -EBADF;
  	file = fget(fd);
  	if (!file)
  		goto out;
  	if (!(file->f_mode & FMODE_WRITE))
  		goto out_fput;
  	/*
  	 * Revalidate the write permissions, in case security policy has
  	 * changed since the files were opened.
  	 */
  	ret = security_file_permission(file, MAY_WRITE);
  	if (ret)
  		goto out_fput;
  
  	inode = file->f_path.dentry->d_inode;
  
  	ret = -ESPIPE;
  	if (S_ISFIFO(inode->i_mode))
  		goto out_fput;
  
  	ret = -ENODEV;
  	/*
  	 * Let individual file system decide if it supports preallocation
  	 * for directories or not.
  	 */
  	if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
  		goto out_fput;
  
  	ret = -EFBIG;
  	/* Check for wrap through zero too */
  	if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
  		goto out_fput;
acfa4380e   Al Viro   inode->i_op is ne...
407
  	if (inode->i_op->fallocate)
97ac73506   Amit Arora   sys_fallocate() i...
408
409
  		ret = inode->i_op->fallocate(inode, mode, offset, len);
  	else
0d786d4a2   Ulrich Drepper   fallocate syscall...
410
  		ret = -EOPNOTSUPP;
97ac73506   Amit Arora   sys_fallocate() i...
411
412
413
414
415
416
  
  out_fput:
  	fput(file);
  out:
  	return ret;
  }
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
417
418
419
420
421
422
423
  #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
  asmlinkage long SyS_fallocate(long fd, long mode, loff_t offset, loff_t len)
  {
  	return SYSC_fallocate((int)fd, (int)mode, offset, len);
  }
  SYSCALL_ALIAS(sys_fallocate, SyS_fallocate);
  #endif
97ac73506   Amit Arora   sys_fallocate() i...
424

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
427
428
429
  /*
   * access() needs to use the real uid/gid, not the effective uid/gid.
   * We do this by temporarily clearing all FS-related capabilities and
   * switching the fsuid/fsgid around to the real ones.
   */
6559eed8c   Heiko Carstens   [CVE-2009-0029] S...
430
  SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  {
d84f4f992   David Howells   CRED: Inaugurate ...
432
433
  	const struct cred *old_cred;
  	struct cred *override_cred;
2d8f30380   Al Viro   [PATCH] sanitize ...
434
  	struct path path;
256984a83   Al Viro   [PATCH] preparati...
435
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
438
439
  	int res;
  
  	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
  		return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
440
441
442
  	override_cred = prepare_creds();
  	if (!override_cred)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443

d84f4f992   David Howells   CRED: Inaugurate ...
444
445
  	override_cred->fsuid = override_cred->uid;
  	override_cred->fsgid = override_cred->gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446

086f7316f   Andrew G. Morgan   security: filesys...
447
  	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
1cdcbec1a   David Howells   CRED: Neuter sys_...
448
  		/* Clear the capabilities if we switch to a non-root user */
d84f4f992   David Howells   CRED: Inaugurate ...
449
450
  		if (override_cred->uid)
  			cap_clear(override_cred->cap_effective);
086f7316f   Andrew G. Morgan   security: filesys...
451
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
452
453
  			override_cred->cap_effective =
  				override_cred->cap_permitted;
086f7316f   Andrew G. Morgan   security: filesys...
454
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455

d84f4f992   David Howells   CRED: Inaugurate ...
456
  	old_cred = override_creds(override_cred);
2d8f30380   Al Viro   [PATCH] sanitize ...
457
  	res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
458
459
  	if (res)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
460
  	inode = path.dentry->d_inode;
256984a83   Al Viro   [PATCH] preparati...
461
462
  
  	if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
30524472c   Al Viro   [PATCH] take noex...
463
464
465
466
467
  		/*
  		 * MAY_EXEC on regular files is denied if the fs is mounted
  		 * with the "noexec" flag.
  		 */
  		res = -EACCES;
2d8f30380   Al Viro   [PATCH] sanitize ...
468
  		if (path.mnt->mnt_flags & MNT_NOEXEC)
30524472c   Al Viro   [PATCH] take noex...
469
470
  			goto out_path_release;
  	}
256984a83   Al Viro   [PATCH] preparati...
471
  	res = inode_permission(inode, mode | MAY_ACCESS);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
472
  	/* SuS v2 requires we report a read only fs too */
256984a83   Al Viro   [PATCH] preparati...
473
  	if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
6902d925d   Dave Hansen   [PATCH] r/o bind ...
474
  		goto out_path_release;
2f676cbc0   Dave Hansen   [PATCH] r/o bind ...
475
476
477
478
479
480
481
482
483
484
  	/*
  	 * This is a rare case where using __mnt_is_readonly()
  	 * is OK without a mnt_want/drop_write() pair.  Since
  	 * no actual write to the fs is performed here, we do
  	 * not need to telegraph to that to anyone.
  	 *
  	 * By doing this, we accept that this access is
  	 * inherently racy and know that the fs may change
  	 * state before we even see this result.
  	 */
2d8f30380   Al Viro   [PATCH] sanitize ...
485
  	if (__mnt_is_readonly(path.mnt))
6902d925d   Dave Hansen   [PATCH] r/o bind ...
486
  		res = -EROFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487

6902d925d   Dave Hansen   [PATCH] r/o bind ...
488
  out_path_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
489
  	path_put(&path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
490
  out:
d84f4f992   David Howells   CRED: Inaugurate ...
491
492
  	revert_creds(old_cred);
  	put_cred(override_cred);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
494
  	return res;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
495
  SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
496
497
498
  {
  	return sys_faccessat(AT_FDCWD, filename, mode);
  }
3cdad4288   Heiko Carstens   [CVE-2009-0029] S...
499
  SYSCALL_DEFINE1(chdir, const char __user *, filename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
501
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
503
  	error = user_path_dir(filename, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
506
  	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
508
  	if (error)
  		goto dput_and_out;
2d8f30380   Al Viro   [PATCH] sanitize ...
509
  	set_fs_pwd(current->fs, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
510
511
  
  dput_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
512
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
515
  out:
  	return error;
  }
3cdad4288   Heiko Carstens   [CVE-2009-0029] S...
516
  SYSCALL_DEFINE1(fchdir, unsigned int, fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
  {
  	struct file *file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
522
523
524
525
  	int error;
  
  	error = -EBADF;
  	file = fget(fd);
  	if (!file)
  		goto out;
ac748a09f   Jan Blunck   Make set_fs_{root...
526
  	inode = file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
530
  
  	error = -ENOTDIR;
  	if (!S_ISDIR(inode->i_mode))
  		goto out_putf;
256984a83   Al Viro   [PATCH] preparati...
531
  	error = inode_permission(inode, MAY_EXEC | MAY_ACCESS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
532
  	if (!error)
ac748a09f   Jan Blunck   Make set_fs_{root...
533
  		set_fs_pwd(current->fs, &file->f_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
  out_putf:
  	fput(file);
  out:
  	return error;
  }
3480b2574   Heiko Carstens   [CVE-2009-0029] S...
539
  SYSCALL_DEFINE1(chroot, const char __user *, filename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
541
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
543
  	error = user_path_dir(filename, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544
545
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
546
  	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
549
550
551
552
  	if (error)
  		goto dput_and_out;
  
  	error = -EPERM;
  	if (!capable(CAP_SYS_CHROOT))
  		goto dput_and_out;
2d8f30380   Al Viro   [PATCH] sanitize ...
553
  	set_fs_root(current->fs, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
  	error = 0;
  dput_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
556
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
  out:
  	return error;
  }
a26eab240   Heiko Carstens   [CVE-2009-0029] S...
560
  SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
562
563
564
565
566
567
568
569
570
  {
  	struct inode * inode;
  	struct dentry * dentry;
  	struct file * file;
  	int err = -EBADF;
  	struct iattr newattrs;
  
  	file = fget(fd);
  	if (!file)
  		goto out;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
571
  	dentry = file->f_path.dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
  	inode = dentry->d_inode;
5a190ae69   Al Viro   [PATCH] pass dent...
573
  	audit_inode(NULL, dentry);
73241ccca   Amy Griffis   [PATCH] Collect m...
574

96029c4e0   npiggin@suse.de   fs: introduce mnt...
575
  	err = mnt_want_write_file(file);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
576
  	if (err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  		goto out_putf;
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
578
  	mutex_lock(&inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
582
583
  	if (mode == (mode_t) -1)
  		mode = inode->i_mode;
  	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
  	err = notify_change(dentry, &newattrs);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
584
  	mutex_unlock(&inode->i_mutex);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
585
  	mnt_drop_write(file->f_path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
589
590
  out_putf:
  	fput(file);
  out:
  	return err;
  }
6559eed8c   Heiko Carstens   [CVE-2009-0029] S...
591
  SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
593
594
  	struct path path;
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
596
  	int error;
  	struct iattr newattrs;
2d8f30380   Al Viro   [PATCH] sanitize ...
597
  	error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
600
  	inode = path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601

2d8f30380   Al Viro   [PATCH] sanitize ...
602
  	error = mnt_want_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
603
  	if (error)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
  		goto dput_and_out;
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
605
  	mutex_lock(&inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
606
607
608
609
  	if (mode == (mode_t) -1)
  		mode = inode->i_mode;
  	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
2d8f30380   Al Viro   [PATCH] sanitize ...
610
  	error = notify_change(path.dentry, &newattrs);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
611
  	mutex_unlock(&inode->i_mutex);
2d8f30380   Al Viro   [PATCH] sanitize ...
612
  	mnt_drop_write(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  dput_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
614
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
617
  out:
  	return error;
  }
a26eab240   Heiko Carstens   [CVE-2009-0029] S...
618
  SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
619
620
621
  {
  	return sys_fchmodat(AT_FDCWD, filename, mode);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
  static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
  {
beb29e058   Miklos Szeredi   [patch 4/4] vfs: ...
624
  	struct inode *inode = dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
626
  	int error;
  	struct iattr newattrs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
629
630
631
632
633
634
635
636
  	newattrs.ia_valid =  ATTR_CTIME;
  	if (user != (uid_t) -1) {
  		newattrs.ia_valid |= ATTR_UID;
  		newattrs.ia_uid = user;
  	}
  	if (group != (gid_t) -1) {
  		newattrs.ia_valid |= ATTR_GID;
  		newattrs.ia_gid = group;
  	}
  	if (!S_ISDIR(inode->i_mode))
b53767719   Serge E. Hallyn   Implement file po...
637
638
  		newattrs.ia_valid |=
  			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
639
  	mutex_lock(&inode->i_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
  	error = notify_change(dentry, &newattrs);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
641
  	mutex_unlock(&inode->i_mutex);
beb29e058   Miklos Szeredi   [patch 4/4] vfs: ...
642

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
  	return error;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
645
  SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
646
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
647
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
649
  	error = user_path(filename, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
650
651
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
652
  	error = mnt_want_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
653
654
  	if (error)
  		goto out_release;
2d8f30380   Al Viro   [PATCH] sanitize ...
655
656
  	error = chown_common(path.dentry, user, group);
  	mnt_drop_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
657
  out_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
658
  	path_put(&path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
659
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
661
  	return error;
  }
6559eed8c   Heiko Carstens   [CVE-2009-0029] S...
662
663
  SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
  		gid_t, group, int, flag)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
664
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
665
  	struct path path;
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
666
667
668
669
670
671
672
  	int error = -EINVAL;
  	int follow;
  
  	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
  		goto out;
  
  	follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
2d8f30380   Al Viro   [PATCH] sanitize ...
673
  	error = user_path_at(dfd, filename, follow, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
674
675
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
676
  	error = mnt_want_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
677
678
  	if (error)
  		goto out_release;
2d8f30380   Al Viro   [PATCH] sanitize ...
679
680
  	error = chown_common(path.dentry, user, group);
  	mnt_drop_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
681
  out_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
682
  	path_put(&path);
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
683
684
685
  out:
  	return error;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
686
  SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
688
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
690
  	error = user_lpath(filename, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
691
692
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
693
  	error = mnt_want_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
694
695
  	if (error)
  		goto out_release;
2d8f30380   Al Viro   [PATCH] sanitize ...
696
697
  	error = chown_common(path.dentry, user, group);
  	mnt_drop_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
698
  out_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
699
  	path_put(&path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
700
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
702
  	return error;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
703
  SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
706
  {
  	struct file * file;
  	int error = -EBADF;
6902d925d   Dave Hansen   [PATCH] r/o bind ...
707
  	struct dentry * dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
  
  	file = fget(fd);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
710
711
  	if (!file)
  		goto out;
96029c4e0   npiggin@suse.de   fs: introduce mnt...
712
  	error = mnt_want_write_file(file);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
713
714
  	if (error)
  		goto out_fput;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
715
  	dentry = file->f_path.dentry;
5a190ae69   Al Viro   [PATCH] pass dent...
716
  	audit_inode(NULL, dentry);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
717
  	error = chown_common(dentry, user, group);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
718
719
  	mnt_drop_write(file->f_path.mnt);
  out_fput:
6902d925d   Dave Hansen   [PATCH] r/o bind ...
720
721
  	fput(file);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
  	return error;
  }
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
  /*
   * You have to be very careful that these write
   * counts get cleaned up in error cases and
   * upon __fput().  This should probably never
   * be called outside of __dentry_open().
   */
  static inline int __get_file_write_access(struct inode *inode,
  					  struct vfsmount *mnt)
  {
  	int error;
  	error = get_write_access(inode);
  	if (error)
  		return error;
  	/*
  	 * Do not take mount writer counts on
  	 * special files since no writes to
  	 * the mount itself will occur.
  	 */
  	if (!special_file(inode->i_mode)) {
  		/*
  		 * Balanced in __fput()
  		 */
  		error = mnt_want_write(mnt);
  		if (error)
  			put_write_access(inode);
  	}
  	return error;
  }
a1a5b3d93   Peter Staubach   [PATCH] open retu...
752
  static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
753
  					int flags, struct file *f,
745ca2475   David Howells   CRED: Pass creden...
754
755
  					int (*open)(struct inode *, struct file *),
  					const struct cred *cred)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
758
  	struct inode *inode;
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  	f->f_flags = flags;
aeb5d7270   Al Viro   [PATCH] introduce...
760
  	f->f_mode = (__force fmode_t)((flags+1) & O_ACCMODE) | FMODE_LSEEK |
a1a5b3d93   Peter Staubach   [PATCH] open retu...
761
  				FMODE_PREAD | FMODE_PWRITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
  	inode = dentry->d_inode;
  	if (f->f_mode & FMODE_WRITE) {
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
764
  		error = __get_file_write_access(inode, mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
  		if (error)
  			goto cleanup_file;
ad775f5a8   Dave Hansen   [PATCH] r/o bind ...
767
768
  		if (!special_file(inode->i_mode))
  			file_take_write(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
771
  	}
  
  	f->f_mapping = inode->i_mapping;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
772
773
  	f->f_path.dentry = dentry;
  	f->f_path.mnt = mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
  	f->f_pos = 0;
  	f->f_op = fops_get(inode->i_fop);
  	file_move(f, &inode->i_sb->s_files);
745ca2475   David Howells   CRED: Pass creden...
777
  	error = security_dentry_open(f, cred);
788e7dd4c   Yuichi Nakamura   SELinux: Improve ...
778
779
  	if (error)
  		goto cleanup_all;
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
780
781
782
783
  	if (!open && f->f_op)
  		open = f->f_op->open;
  	if (open) {
  		error = open(inode, f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
785
786
  		if (error)
  			goto cleanup_all;
  	}
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
787

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
790
791
792
793
  	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
  
  	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
  
  	/* NB: we're sure to have correct a_ops only after f_op->open */
  	if (f->f_flags & O_DIRECT) {
ceffc0785   Carsten Otte   [PATCH] xip: fs/m...
794
795
  		if (!f->f_mapping->a_ops ||
  		    ((!f->f_mapping->a_ops->direct_IO) &&
70688e4dd   Nick Piggin   xip: support non-...
796
  		    (!f->f_mapping->a_ops->get_xip_mem))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
799
800
801
802
803
804
805
  			fput(f);
  			f = ERR_PTR(-EINVAL);
  		}
  	}
  
  	return f;
  
  cleanup_all:
  	fops_put(f->f_op);
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
806
  	if (f->f_mode & FMODE_WRITE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  		put_write_access(inode);
ad775f5a8   Dave Hansen   [PATCH] r/o bind ...
808
809
810
811
812
813
814
815
  		if (!special_file(inode->i_mode)) {
  			/*
  			 * We don't consider this a real
  			 * mnt_want/drop_write() pair
  			 * because it all happenend right
  			 * here, so just reset the state.
  			 */
  			file_reset_write(f);
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
816
  			mnt_drop_write(mnt);
ad775f5a8   Dave Hansen   [PATCH] r/o bind ...
817
  		}
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
818
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  	file_kill(f);
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
820
821
  	f->f_path.dentry = NULL;
  	f->f_path.mnt = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
  cleanup_file:
  	put_filp(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
826
827
  	dput(dentry);
  	mntput(mnt);
  	return ERR_PTR(error);
  }
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
828
829
830
831
832
833
834
835
836
837
  /**
   * lookup_instantiate_filp - instantiates the open intent filp
   * @nd: pointer to nameidata
   * @dentry: pointer to dentry
   * @open: open callback
   *
   * Helper for filesystems that want to use lookup open intents and pass back
   * a fully instantiated struct file to the caller.
   * This function is meant to be called from within a filesystem's
   * lookup method.
9a56c2139   Oleg Drokin   [PATCH] Add looku...
838
839
840
841
   * Beware of calling it for non-regular files! Those ->open methods might block
   * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
   * leading to a deadlock, as nobody can open that fifo anymore, because
   * another process to open fifo will block on locked parent when doing lookup).
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
842
843
844
845
846
847
848
849
   * Note that in case of error, nd->intent.open.file is destroyed, but the
   * path information remains valid.
   * If the open callback is set to NULL, then the standard f_op->open()
   * filesystem callback is substituted.
   */
  struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
  		int (*open)(struct inode *, struct file *))
  {
745ca2475   David Howells   CRED: Pass creden...
850
  	const struct cred *cred = current_cred();
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
851
852
853
854
  	if (IS_ERR(nd->intent.open.file))
  		goto out;
  	if (IS_ERR(dentry))
  		goto out_err;
4ac913785   Jan Blunck   Embed a struct pa...
855
  	nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
856
857
  					     nd->intent.open.flags - 1,
  					     nd->intent.open.file,
745ca2475   David Howells   CRED: Pass creden...
858
  					     open, cred);
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
  out:
  	return nd->intent.open.file;
  out_err:
  	release_open_intent(nd);
  	nd->intent.open.file = (struct file *)dentry;
  	goto out;
  }
  EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
  
  /**
   * nameidata_to_filp - convert a nameidata to an open filp.
   * @nd: pointer to nameidata
   * @flags: open flags
   *
   * Note that this function destroys the original nameidata
   */
  struct file *nameidata_to_filp(struct nameidata *nd, int flags)
  {
745ca2475   David Howells   CRED: Pass creden...
877
  	const struct cred *cred = current_cred();
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
878
879
880
881
882
  	struct file *filp;
  
  	/* Pick up the filp from the open intent */
  	filp = nd->intent.open.file;
  	/* Has the filesystem initialised the file for us? */
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
883
  	if (filp->f_path.dentry == NULL)
4ac913785   Jan Blunck   Embed a struct pa...
884
  		filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp,
745ca2475   David Howells   CRED: Pass creden...
885
  				     NULL, cred);
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
886
  	else
1d957f9bf   Jan Blunck   Introduce path_put()
887
  		path_put(&nd->path);
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
888
889
  	return filp;
  }
6fdcc2162   Peter Staubach   [PATCH] memory le...
890
891
892
893
  /*
   * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
   * error.
   */
745ca2475   David Howells   CRED: Pass creden...
894
895
  struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
  			 const struct cred *cred)
a1a5b3d93   Peter Staubach   [PATCH] open retu...
896
897
898
  {
  	int error;
  	struct file *f;
322ee5b36   Christoph Hellwig   [PATCH] check for...
899
900
901
902
903
904
905
906
907
908
909
910
  	/*
  	 * We must always pass in a valid mount pointer.   Historically
  	 * callers got away with not passing it, but we must enforce this at
  	 * the earliest possible point now to avoid strange problems deep in the
  	 * filesystem stack.
  	 */
  	if (!mnt) {
  		printk(KERN_WARNING "%s called with NULL vfsmount
  ", __func__);
  		dump_stack();
  		return ERR_PTR(-EINVAL);
  	}
a1a5b3d93   Peter Staubach   [PATCH] open retu...
911
912
  	error = -ENFILE;
  	f = get_empty_filp();
6fdcc2162   Peter Staubach   [PATCH] memory le...
913
914
915
  	if (f == NULL) {
  		dput(dentry);
  		mntput(mnt);
a1a5b3d93   Peter Staubach   [PATCH] open retu...
916
  		return ERR_PTR(error);
6fdcc2162   Peter Staubach   [PATCH] memory le...
917
  	}
a1a5b3d93   Peter Staubach   [PATCH] open retu...
918

745ca2475   David Howells   CRED: Pass creden...
919
  	return __dentry_open(dentry, mnt, flags, f, NULL, cred);
a1a5b3d93   Peter Staubach   [PATCH] open retu...
920
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  EXPORT_SYMBOL(dentry_open);
b01ec0ef6   Matt Mackall   [PATCH] tiny: Uni...
922
  static void __put_unused_fd(struct files_struct *files, unsigned int fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
  {
badf16621   Dipankar Sarma   [PATCH] files: br...
924
925
  	struct fdtable *fdt = files_fdtable(files);
  	__FD_CLR(fd, fdt->open_fds);
0c9e63fd3   Eric Dumazet   [PATCH] Shrinks s...
926
927
  	if (fd < files->next_fd)
  		files->next_fd = fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
928
  }
fc9b52cd8   Harvey Harrison   fs: remove fastca...
929
  void put_unused_fd(unsigned int fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
933
934
935
936
937
938
939
  {
  	struct files_struct *files = current->files;
  	spin_lock(&files->file_lock);
  	__put_unused_fd(files, fd);
  	spin_unlock(&files->file_lock);
  }
  
  EXPORT_SYMBOL(put_unused_fd);
  
  /*
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
940
   * Install a file pointer in the fd array.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
941
942
943
944
945
946
947
948
949
950
   *
   * The VFS is full of places where we drop the files lock between
   * setting the open_fds bitmap and installing the file in the file
   * array.  At any such point, we are vulnerable to a dup2() race
   * installing a file in the array before us.  We need to detect this and
   * fput() the struct file we are about to overwrite in this case.
   *
   * It should never happen - if we allow dup2() do it, _really_ bad things
   * will follow.
   */
fc9b52cd8   Harvey Harrison   fs: remove fastca...
951
  void fd_install(unsigned int fd, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
952
953
  {
  	struct files_struct *files = current->files;
badf16621   Dipankar Sarma   [PATCH] files: br...
954
  	struct fdtable *fdt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
  	spin_lock(&files->file_lock);
badf16621   Dipankar Sarma   [PATCH] files: br...
956
  	fdt = files_fdtable(files);
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
957
958
  	BUG_ON(fdt->fd[fd] != NULL);
  	rcu_assign_pointer(fdt->fd[fd], file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
960
961
962
  	spin_unlock(&files->file_lock);
  }
  
  EXPORT_SYMBOL(fd_install);
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
963
  long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
964
  {
e922efc34   Miklos Szeredi   [PATCH] remove du...
965
966
  	char *tmp = getname(filename);
  	int fd = PTR_ERR(tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968
  	if (!IS_ERR(tmp)) {
f23513e8d   Ulrich Drepper   Introduce O_CLOEXEC
969
  		fd = get_unused_fd_flags(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
970
  		if (fd >= 0) {
6e8341a11   Al Viro   Switch open_exec(...
971
  			struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
fed2fc18a   Telemaque Ndizihiwe   [PATCH] sys_open(...
972
973
974
975
  			if (IS_ERR(f)) {
  				put_unused_fd(fd);
  				fd = PTR_ERR(f);
  			} else {
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
976
  				fsnotify_open(f->f_path.dentry);
fed2fc18a   Telemaque Ndizihiwe   [PATCH] sys_open(...
977
978
  				fd_install(fd, f);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
  		putname(tmp);
  	}
  	return fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
983
  }
e922efc34   Miklos Szeredi   [PATCH] remove du...
984

ca013e945   Heiko Carstens   [CVE-2009-0029] S...
985
  SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
e922efc34   Miklos Szeredi   [PATCH] remove du...
986
  {
385910f2b   Linus Torvalds   x86: be careful a...
987
  	long ret;
e922efc34   Miklos Szeredi   [PATCH] remove du...
988
989
  	if (force_o_largefile())
  		flags |= O_LARGEFILE;
385910f2b   Linus Torvalds   x86: be careful a...
990
991
  	ret = do_sys_open(AT_FDCWD, filename, flags, mode);
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
992
  	asmlinkage_protect(3, ret, filename, flags, mode);
385910f2b   Linus Torvalds   x86: be careful a...
993
  	return ret;
e922efc34   Miklos Szeredi   [PATCH] remove du...
994
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
995

6559eed8c   Heiko Carstens   [CVE-2009-0029] S...
996
997
  SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
  		int, mode)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
998
  {
385910f2b   Linus Torvalds   x86: be careful a...
999
  	long ret;
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
1000
1001
  	if (force_o_largefile())
  		flags |= O_LARGEFILE;
385910f2b   Linus Torvalds   x86: be careful a...
1002
1003
  	ret = do_sys_open(dfd, filename, flags, mode);
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
1004
  	asmlinkage_protect(4, ret, dfd, filename, flags, mode);
385910f2b   Linus Torvalds   x86: be careful a...
1005
  	return ret;
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
1006
  }
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
1007

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
1009
1010
1011
1012
1013
  #ifndef __alpha__
  
  /*
   * For backward compatibility?  Maybe this should be moved
   * into arch/i386 instead?
   */
002c8976e   Heiko Carstens   [CVE-2009-0029] S...
1014
  SYSCALL_DEFINE2(creat, const char __user *, pathname, int, mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
  {
  	return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
  }
  
  #endif
  
  /*
   * "id" is the POSIX thread ID. We use the
   * files pointer for this..
   */
  int filp_close(struct file *filp, fl_owner_t id)
  {
45778ca81   Christoph Lameter   [PATCH] Remove f_...
1027
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
1029
1030
1031
  
  	if (!file_count(filp)) {
  		printk(KERN_ERR "VFS: Close: file count is 0
  ");
45778ca81   Christoph Lameter   [PATCH] Remove f_...
1032
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1033
  	}
45778ca81   Christoph Lameter   [PATCH] Remove f_...
1034
  	if (filp->f_op && filp->f_op->flush)
75e1fcc0b   Miklos Szeredi   [PATCH] vfs: add ...
1035
  		retval = filp->f_op->flush(filp, id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  
  	dnotify_flush(filp, id);
  	locks_remove_posix(filp, id);
  	fput(filp);
  	return retval;
  }
  
  EXPORT_SYMBOL(filp_close);
  
  /*
   * Careful here! We test whether the file pointer is NULL before
   * releasing the fd. This ensures that one clone task can't release
   * an fd while another clone is opening it.
   */
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
1050
  SYSCALL_DEFINE1(close, unsigned int, fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1051
1052
1053
  {
  	struct file * filp;
  	struct files_struct *files = current->files;
badf16621   Dipankar Sarma   [PATCH] files: br...
1054
  	struct fdtable *fdt;
ee731f4f7   Ernie Petrides   [PATCH] fix wrong...
1055
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1056
1057
  
  	spin_lock(&files->file_lock);
badf16621   Dipankar Sarma   [PATCH] files: br...
1058
1059
  	fdt = files_fdtable(files);
  	if (fd >= fdt->max_fds)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
  		goto out_unlock;
badf16621   Dipankar Sarma   [PATCH] files: br...
1061
  	filp = fdt->fd[fd];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1062
1063
  	if (!filp)
  		goto out_unlock;
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
1064
  	rcu_assign_pointer(fdt->fd[fd], NULL);
badf16621   Dipankar Sarma   [PATCH] files: br...
1065
  	FD_CLR(fd, fdt->close_on_exec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1066
1067
  	__put_unused_fd(files, fd);
  	spin_unlock(&files->file_lock);
ee731f4f7   Ernie Petrides   [PATCH] fix wrong...
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
  	retval = filp_close(filp, files);
  
  	/* can't restart close syscall because file table entry was cleared */
  	if (unlikely(retval == -ERESTARTSYS ||
  		     retval == -ERESTARTNOINTR ||
  		     retval == -ERESTARTNOHAND ||
  		     retval == -ERESTART_RESTARTBLOCK))
  		retval = -EINTR;
  
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
1080
1081
1082
  
  out_unlock:
  	spin_unlock(&files->file_lock);
  	return -EBADF;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
1085
1086
1087
1088
  EXPORT_SYMBOL(sys_close);
  
  /*
   * This routine simulates a hangup on the tty, to arrange that users
   * are given clean terminals at login time.
   */
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
1089
  SYSCALL_DEFINE0(vhangup)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1090
1091
  {
  	if (capable(CAP_SYS_TTY_CONFIG)) {
2cb5998b5   Alan Cox   tty: the vhangup ...
1092
  		tty_vhangup_self();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
  		return 0;
  	}
  	return -EPERM;
  }
  
  /*
   * Called when an inode is about to be open.
   * We use this to disallow opening large files on 32bit systems if
   * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
   * on this flag in sys_open.
   */
  int generic_file_open(struct inode * inode, struct file * filp)
  {
  	if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
a9c62a18a   Alan Cox   fs: correct SuS c...
1107
  		return -EOVERFLOW;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
  	return 0;
  }
  
  EXPORT_SYMBOL(generic_file_open);
  
  /*
   * This is used by subsystems that don't want seekable
   * file descriptors
   */
  int nonseekable_open(struct inode *inode, struct file *filp)
  {
  	filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
  	return 0;
  }
  
  EXPORT_SYMBOL(nonseekable_open);