Blame view

fs/open.c 26.3 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>
0eeca2830   Robert Love   [PATCH] inotify
11
  #include <linux/fsnotify.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
13
14
15
  #include <linux/tty.h>
  #include <linux/namei.h>
  #include <linux/backing-dev.h>
16f7e0fe2   Randy Dunlap   [PATCH] capable/c...
16
  #include <linux/capability.h>
086f7316f   Andrew G. Morgan   security: filesys...
17
  #include <linux/securebits.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
  #include <linux/security.h>
  #include <linux/mount.h>
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
20
  #include <linux/fcntl.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
  #include <asm/uaccess.h>
  #include <linux/fs.h>
ef3daeda7   Yoav Zach   [PATCH] Don't for...
24
  #include <linux/personality.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
  #include <linux/pagemap.h>
  #include <linux/syscalls.h>
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
27
  #include <linux/rcupdate.h>
73241ccca   Amy Griffis   [PATCH] Collect m...
28
  #include <linux/audit.h>
97ac73506   Amit Arora   sys_fallocate() i...
29
  #include <linux/falloc.h>
5ad4e53bd   Al Viro   Get rid of indire...
30
  #include <linux/fs_struct.h>
b65a9cfc2   Al Viro   Untangling ima me...
31
  #include <linux/ima.h>
2dfc1cae4   Eric Paris   inotify: remove i...
32
  #include <linux/dnotify.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

e81e3f4dc   Eric Paris   fs: move get_empt...
34
  #include "internal.h"
4a30131e7   NeilBrown   [PATCH] Fix some ...
35
36
  int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
  	struct file *filp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  {
939a9421e   Amerigo Wang   vfs: allow file t...
38
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
44
45
  	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 ...
46
  	newattrs.ia_valid = ATTR_SIZE | time_attrs;
cc4e69dee   Miklos Szeredi   [PATCH] VFS: pass...
47
48
49
50
  	if (filp) {
  		newattrs.ia_file = filp;
  		newattrs.ia_valid |= ATTR_FILE;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51

7b82dc0e6   Linus Torvalds   Remove suid/sgid ...
52
  	/* Remove suid/sgid on truncate too */
939a9421e   Amerigo Wang   vfs: allow file t...
53
54
55
  	ret = should_remove_suid(dentry);
  	if (ret)
  		newattrs.ia_valid |= ret | ATTR_FORCE;
7b82dc0e6   Linus Torvalds   Remove suid/sgid ...
56

1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
57
  	mutex_lock(&dentry->d_inode->i_mutex);
939a9421e   Amerigo Wang   vfs: allow file t...
58
  	ret = notify_change(dentry, &newattrs);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
59
  	mutex_unlock(&dentry->d_inode->i_mutex);
939a9421e   Amerigo Wang   vfs: allow file t...
60
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
  }
2d8f30380   Al Viro   [PATCH] sanitize ...
62
  static long do_sys_truncate(const char __user *pathname, loff_t length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
64
65
  	struct path path;
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
70
  	int error;
  
  	error = -EINVAL;
  	if (length < 0)	/* sorry, but loff_t says... */
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
71
  	error = user_path(pathname, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
74
  	inode = path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
81
82
83
  
  	/* 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 ...
84
  	error = mnt_want_write(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  	if (error)
  		goto dput_and_out;
256984a83   Al Viro   [PATCH] preparati...
87
  	error = inode_permission(inode, MAY_WRITE);
9ac9b8474   Dave Hansen   [PATCH] r/o bind ...
88
89
  	if (error)
  		goto mnt_drop_write_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
  
  	error = -EPERM;
c82e42da8   Miklos Szeredi   [patch 1/5] vfs: ...
92
  	if (IS_APPEND(inode))
9ac9b8474   Dave Hansen   [PATCH] r/o bind ...
93
  		goto mnt_drop_write_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94

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

9700382c3   david m. richter   VFS: fix a race i...
99
100
101
102
  	/*
  	 * Make sure that there are no leases.  get_write_access() protects
  	 * against the truncate racing with a lease-granting setlease().
  	 */
8737c9305   Al Viro   Switch may_open()...
103
  	error = break_lease(inode, O_WRONLY);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  	if (error)
9700382c3   david m. richter   VFS: fix a race i...
105
  		goto put_write_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  
  	error = locks_verify_truncate(inode, NULL, length);
be6d3e56a   Kentaro Takeda   introduce new LSM...
108
  	if (!error)
ea0d3ab23   Tetsuo Handa   LSM: Remove unuse...
109
  		error = security_path_truncate(&path);
907f4554e   Christoph Hellwig   dquot: move dquot...
110
  	if (!error)
2d8f30380   Al Viro   [PATCH] sanitize ...
111
  		error = do_truncate(path.dentry, length, 0, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112

9700382c3   david m. richter   VFS: fix a race i...
113
114
  put_write_and_out:
  	put_write_access(inode);
9ac9b8474   Dave Hansen   [PATCH] r/o bind ...
115
  mnt_drop_write_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
116
  	mnt_drop_write(path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117
  dput_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
118
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
  out:
  	return error;
  }
4fd8da8d6   Heiko Carstens   fs: change sys_tr...
122
  SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
  {
4fd8da8d6   Heiko Carstens   fs: change sys_tr...
124
  	return do_sys_truncate(path, length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  }
b01ec0ef6   Matt Mackall   [PATCH] tiny: Uni...
126
  static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  {
  	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...
144
  	dentry = file->f_path.dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  	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)
ea0d3ab23   Tetsuo Handa   LSM: Remove unuse...
161
  		error = security_path_truncate(&file->f_path);
be6d3e56a   Kentaro Takeda   introduce new LSM...
162
  	if (!error)
6e656be89   Peter Staubach   [PATCH] ftruncate...
163
  		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
  out_putf:
  	fput(file);
  out:
  	return error;
  }
bdc480e3b   Heiko Carstens   [CVE-2009-0029] S...
169
  SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  {
0a489cb3b   Linus Torvalds   x86: don't allow ...
171
  	long ret = do_sys_ftruncate(fd, length, 1);
385910f2b   Linus Torvalds   x86: be careful a...
172
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
173
  	asmlinkage_protect(2, ret, fd, length);
0a489cb3b   Linus Torvalds   x86: don't allow ...
174
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
  }
  
  /* LFS versions of truncate are only needed on 32 bit machines */
  #if BITS_PER_LONG == 32
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
179
  SYSCALL_DEFINE(truncate64)(const char __user * path, loff_t length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
  {
  	return do_sys_truncate(path, length);
  }
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
183
184
185
186
187
188
189
  #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
190

6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
191
  SYSCALL_DEFINE(ftruncate64)(unsigned int fd, loff_t length)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  {
0a489cb3b   Linus Torvalds   x86: don't allow ...
193
  	long ret = do_sys_ftruncate(fd, length, 0);
385910f2b   Linus Torvalds   x86: be careful a...
194
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
195
  	asmlinkage_protect(2, ret, fd, length);
0a489cb3b   Linus Torvalds   x86: don't allow ...
196
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  }
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
198
199
200
201
202
203
  #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
204
  #endif
6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
205
  #endif /* BITS_PER_LONG == 32 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

3e63cbb1e   Ankit Jain   fs: Add new pre-a...
207
208
  
  int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
97ac73506   Amit Arora   sys_fallocate() i...
209
  {
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
210
211
  	struct inode *inode = file->f_path.dentry->d_inode;
  	long ret;
97ac73506   Amit Arora   sys_fallocate() i...
212
213
  
  	if (offset < 0 || len <= 0)
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
214
  		return -EINVAL;
97ac73506   Amit Arora   sys_fallocate() i...
215
216
  
  	/* Return error if mode is not supported */
79124f18b   Josef Bacik   fs: add hole punc...
217
218
219
220
221
222
  	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
  		return -EOPNOTSUPP;
  
  	/* Punch hole must have keep size set */
  	if ((mode & FALLOC_FL_PUNCH_HOLE) &&
  	    !(mode & FALLOC_FL_KEEP_SIZE))
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
223
  		return -EOPNOTSUPP;
97ac73506   Amit Arora   sys_fallocate() i...
224

97ac73506   Amit Arora   sys_fallocate() i...
225
  	if (!(file->f_mode & FMODE_WRITE))
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
226
  		return -EBADF;
1ca551c6c   Marco Stornelli   Check for immutab...
227
228
229
230
231
232
233
  
  	/* It's not possible punch hole on append only file */
  	if (mode & FALLOC_FL_PUNCH_HOLE && IS_APPEND(inode))
  		return -EPERM;
  
  	if (IS_IMMUTABLE(inode))
  		return -EPERM;
97ac73506   Amit Arora   sys_fallocate() i...
234
235
236
237
238
239
  	/*
  	 * Revalidate the write permissions, in case security policy has
  	 * changed since the files were opened.
  	 */
  	ret = security_file_permission(file, MAY_WRITE);
  	if (ret)
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
240
  		return ret;
97ac73506   Amit Arora   sys_fallocate() i...
241

97ac73506   Amit Arora   sys_fallocate() i...
242
  	if (S_ISFIFO(inode->i_mode))
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
243
  		return -ESPIPE;
97ac73506   Amit Arora   sys_fallocate() i...
244

97ac73506   Amit Arora   sys_fallocate() i...
245
246
247
248
249
  	/*
  	 * Let individual file system decide if it supports preallocation
  	 * for directories or not.
  	 */
  	if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
250
  		return -ENODEV;
97ac73506   Amit Arora   sys_fallocate() i...
251

97ac73506   Amit Arora   sys_fallocate() i...
252
253
  	/* Check for wrap through zero too */
  	if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
254
  		return -EFBIG;
97ac73506   Amit Arora   sys_fallocate() i...
255

2fe17c107   Christoph Hellwig   fallocate should ...
256
  	if (!file->f_op->fallocate)
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
257
  		return -EOPNOTSUPP;
97ac73506   Amit Arora   sys_fallocate() i...
258

2fe17c107   Christoph Hellwig   fallocate should ...
259
  	return file->f_op->fallocate(file, mode, offset, len);
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  }
  
  SYSCALL_DEFINE(fallocate)(int fd, int mode, loff_t offset, loff_t len)
  {
  	struct file *file;
  	int error = -EBADF;
  
  	file = fget(fd);
  	if (file) {
  		error = do_fallocate(file, mode, offset, len);
  		fput(file);
  	}
  
  	return error;
97ac73506   Amit Arora   sys_fallocate() i...
274
  }
3e63cbb1e   Ankit Jain   fs: Add new pre-a...
275

6673e0c3f   Heiko Carstens   [CVE-2009-0029] S...
276
277
278
279
280
281
282
  #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...
283

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
286
287
288
  /*
   * 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...
289
  SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
  {
d84f4f992   David Howells   CRED: Inaugurate ...
291
292
  	const struct cred *old_cred;
  	struct cred *override_cred;
2d8f30380   Al Viro   [PATCH] sanitize ...
293
  	struct path path;
256984a83   Al Viro   [PATCH] preparati...
294
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
  	int res;
  
  	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
  		return -EINVAL;
d84f4f992   David Howells   CRED: Inaugurate ...
299
300
301
  	override_cred = prepare_creds();
  	if (!override_cred)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302

d84f4f992   David Howells   CRED: Inaugurate ...
303
304
  	override_cred->fsuid = override_cred->uid;
  	override_cred->fsgid = override_cred->gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305

086f7316f   Andrew G. Morgan   security: filesys...
306
  	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
1cdcbec1a   David Howells   CRED: Neuter sys_...
307
  		/* Clear the capabilities if we switch to a non-root user */
d84f4f992   David Howells   CRED: Inaugurate ...
308
309
  		if (override_cred->uid)
  			cap_clear(override_cred->cap_effective);
086f7316f   Andrew G. Morgan   security: filesys...
310
  		else
d84f4f992   David Howells   CRED: Inaugurate ...
311
312
  			override_cred->cap_effective =
  				override_cred->cap_permitted;
086f7316f   Andrew G. Morgan   security: filesys...
313
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

d84f4f992   David Howells   CRED: Inaugurate ...
315
  	old_cred = override_creds(override_cred);
2d8f30380   Al Viro   [PATCH] sanitize ...
316
  	res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
317
318
  	if (res)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
319
  	inode = path.dentry->d_inode;
256984a83   Al Viro   [PATCH] preparati...
320
321
  
  	if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
30524472c   Al Viro   [PATCH] take noex...
322
323
324
325
326
  		/*
  		 * MAY_EXEC on regular files is denied if the fs is mounted
  		 * with the "noexec" flag.
  		 */
  		res = -EACCES;
2d8f30380   Al Viro   [PATCH] sanitize ...
327
  		if (path.mnt->mnt_flags & MNT_NOEXEC)
30524472c   Al Viro   [PATCH] take noex...
328
329
  			goto out_path_release;
  	}
256984a83   Al Viro   [PATCH] preparati...
330
  	res = inode_permission(inode, mode | MAY_ACCESS);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
331
  	/* SuS v2 requires we report a read only fs too */
256984a83   Al Viro   [PATCH] preparati...
332
  	if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
6902d925d   Dave Hansen   [PATCH] r/o bind ...
333
  		goto out_path_release;
2f676cbc0   Dave Hansen   [PATCH] r/o bind ...
334
335
336
337
338
339
340
341
342
343
  	/*
  	 * 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 ...
344
  	if (__mnt_is_readonly(path.mnt))
6902d925d   Dave Hansen   [PATCH] r/o bind ...
345
  		res = -EROFS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346

6902d925d   Dave Hansen   [PATCH] r/o bind ...
347
  out_path_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
348
  	path_put(&path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
349
  out:
d84f4f992   David Howells   CRED: Inaugurate ...
350
351
  	revert_creds(old_cred);
  	put_cred(override_cred);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  	return res;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
354
  SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
355
356
357
  {
  	return sys_faccessat(AT_FDCWD, filename, mode);
  }
3cdad4288   Heiko Carstens   [CVE-2009-0029] S...
358
  SYSCALL_DEFINE1(chdir, const char __user *, filename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
360
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
362
  	error = user_path_dir(filename, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
  	if (error)
  		goto out;
9cfcac810   Eric Paris   vfs: re-introduce...
365
  	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
367
  	if (error)
  		goto dput_and_out;
2d8f30380   Al Viro   [PATCH] sanitize ...
368
  	set_fs_pwd(current->fs, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
  
  dput_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
371
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
  out:
  	return error;
  }
3cdad4288   Heiko Carstens   [CVE-2009-0029] S...
375
  SYSCALL_DEFINE1(fchdir, unsigned int, fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  {
  	struct file *file;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
383
384
  	int error;
  
  	error = -EBADF;
  	file = fget(fd);
  	if (!file)
  		goto out;
ac748a09f   Jan Blunck   Make set_fs_{root...
385
  	inode = file->f_path.dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
389
  
  	error = -ENOTDIR;
  	if (!S_ISDIR(inode->i_mode))
  		goto out_putf;
9cfcac810   Eric Paris   vfs: re-introduce...
390
  	error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  	if (!error)
ac748a09f   Jan Blunck   Make set_fs_{root...
392
  		set_fs_pwd(current->fs, &file->f_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
  out_putf:
  	fput(file);
  out:
  	return error;
  }
3480b2574   Heiko Carstens   [CVE-2009-0029] S...
398
  SYSCALL_DEFINE1(chroot, const char __user *, filename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
400
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
402
  	error = user_path_dir(filename, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
  	if (error)
  		goto out;
9cfcac810   Eric Paris   vfs: re-introduce...
405
  	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
409
410
411
  	if (error)
  		goto dput_and_out;
  
  	error = -EPERM;
  	if (!capable(CAP_SYS_CHROOT))
  		goto dput_and_out;
8b8efb440   Tetsuo Handa   LSM: Add security...
412
413
414
  	error = security_path_chroot(&path);
  	if (error)
  		goto dput_and_out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415

2d8f30380   Al Viro   [PATCH] sanitize ...
416
  	set_fs_root(current->fs, &path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
  	error = 0;
  dput_and_out:
2d8f30380   Al Viro   [PATCH] sanitize ...
419
  	path_put(&path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
  out:
  	return error;
  }
e57712ebe   Al Viro   merge fchmod() an...
423
  static int chmod_common(struct path *path, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
  {
e57712ebe   Al Viro   merge fchmod() an...
425
  	struct inode *inode = path->dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
  	struct iattr newattrs;
e57712ebe   Al Viro   merge fchmod() an...
427
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428

e57712ebe   Al Viro   merge fchmod() an...
429
430
431
  	error = mnt_want_write(path->mnt);
  	if (error)
  		return error;
fe542cf59   Tetsuo Handa   LSM: Move securit...
432
  	mutex_lock(&inode->i_mutex);
cdcf116d4   Al Viro   switch security_p...
433
  	error = security_path_chmod(path, mode);
e57712ebe   Al Viro   merge fchmod() an...
434
  	if (error)
fe542cf59   Tetsuo Handa   LSM: Move securit...
435
  		goto out_unlock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
437
  	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
e57712ebe   Al Viro   merge fchmod() an...
438
  	error = notify_change(path->dentry, &newattrs);
fe542cf59   Tetsuo Handa   LSM: Move securit...
439
  out_unlock:
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
440
  	mutex_unlock(&inode->i_mutex);
e57712ebe   Al Viro   merge fchmod() an...
441
442
443
  	mnt_drop_write(path->mnt);
  	return error;
  }
49f0a0767   Al Viro   switch sys_chmod(...
444
  SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
e57712ebe   Al Viro   merge fchmod() an...
445
446
447
448
449
450
451
452
453
454
  {
  	struct file * file;
  	int err = -EBADF;
  
  	file = fget(fd);
  	if (file) {
  		audit_inode(NULL, file->f_path.dentry);
  		err = chmod_common(&file->f_path, mode);
  		fput(file);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
456
  	return err;
  }
49f0a0767   Al Viro   switch sys_chmod(...
457
  SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
459
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  	int error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461

2d8f30380   Al Viro   [PATCH] sanitize ...
462
  	error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
e57712ebe   Al Viro   merge fchmod() an...
463
464
465
466
  	if (!error) {
  		error = chmod_common(&path, mode);
  		path_put(&path);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
  	return error;
  }
49f0a0767   Al Viro   switch sys_chmod(...
469
  SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
470
471
472
  {
  	return sys_fchmodat(AT_FDCWD, filename, mode);
  }
fe542cf59   Tetsuo Handa   LSM: Move securit...
473
  static int chown_common(struct path *path, uid_t user, gid_t group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  {
fe542cf59   Tetsuo Handa   LSM: Move securit...
475
  	struct inode *inode = path->dentry->d_inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
  	int error;
  	struct iattr newattrs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
481
482
483
484
485
486
487
  	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...
488
489
  		newattrs.ia_valid |=
  			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
490
  	mutex_lock(&inode->i_mutex);
fe542cf59   Tetsuo Handa   LSM: Move securit...
491
492
493
  	error = security_path_chown(path, user, group);
  	if (!error)
  		error = notify_change(path->dentry, &newattrs);
1b1dcc1b5   Jes Sorensen   [PATCH] mutex sub...
494
  	mutex_unlock(&inode->i_mutex);
beb29e058   Miklos Szeredi   [patch 4/4] vfs: ...
495

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
  	return error;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
498
  SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
500
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
502
  	error = user_path(filename, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
503
504
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
505
  	error = mnt_want_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
506
507
  	if (error)
  		goto out_release;
fe542cf59   Tetsuo Handa   LSM: Move securit...
508
  	error = chown_common(&path, user, group);
2d8f30380   Al Viro   [PATCH] sanitize ...
509
  	mnt_drop_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
510
  out_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
511
  	path_put(&path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
512
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
514
  	return error;
  }
6559eed8c   Heiko Carstens   [CVE-2009-0029] S...
515
516
  SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
  		gid_t, group, int, flag)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
517
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
518
  	struct path path;
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
519
  	int error = -EINVAL;
65cfc6722   Al Viro   readlinkat(), fch...
520
  	int lookup_flags;
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
521

65cfc6722   Al Viro   readlinkat(), fch...
522
  	if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
523
  		goto out;
65cfc6722   Al Viro   readlinkat(), fch...
524
525
526
527
  	lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
  	if (flag & AT_EMPTY_PATH)
  		lookup_flags |= LOOKUP_EMPTY;
  	error = user_path_at(dfd, filename, lookup_flags, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
528
529
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
530
  	error = mnt_want_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
531
532
  	if (error)
  		goto out_release;
fe542cf59   Tetsuo Handa   LSM: Move securit...
533
  	error = chown_common(&path, user, group);
2d8f30380   Al Viro   [PATCH] sanitize ...
534
  	mnt_drop_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
535
  out_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
536
  	path_put(&path);
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
537
538
539
  out:
  	return error;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
540
  SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
  {
2d8f30380   Al Viro   [PATCH] sanitize ...
542
  	struct path path;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
  	int error;
2d8f30380   Al Viro   [PATCH] sanitize ...
544
  	error = user_lpath(filename, &path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
545
546
  	if (error)
  		goto out;
2d8f30380   Al Viro   [PATCH] sanitize ...
547
  	error = mnt_want_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
548
549
  	if (error)
  		goto out_release;
fe542cf59   Tetsuo Handa   LSM: Move securit...
550
  	error = chown_common(&path, user, group);
2d8f30380   Al Viro   [PATCH] sanitize ...
551
  	mnt_drop_write(path.mnt);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
552
  out_release:
2d8f30380   Al Viro   [PATCH] sanitize ...
553
  	path_put(&path);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
554
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
  	return error;
  }
ca013e945   Heiko Carstens   [CVE-2009-0029] S...
557
  SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
560
  {
  	struct file * file;
  	int error = -EBADF;
6902d925d   Dave Hansen   [PATCH] r/o bind ...
561
  	struct dentry * dentry;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
  
  	file = fget(fd);
6902d925d   Dave Hansen   [PATCH] r/o bind ...
564
565
  	if (!file)
  		goto out;
96029c4e0   npiggin@suse.de   fs: introduce mnt...
566
  	error = mnt_want_write_file(file);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
567
568
  	if (error)
  		goto out_fput;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
569
  	dentry = file->f_path.dentry;
5a190ae69   Al Viro   [PATCH] pass dent...
570
  	audit_inode(NULL, dentry);
fe542cf59   Tetsuo Handa   LSM: Move securit...
571
  	error = chown_common(&file->f_path, user, group);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
572
  	mnt_drop_write_file(file);
2af482a7e   Dave Hansen   [PATCH] r/o bind ...
573
  out_fput:
6902d925d   Dave Hansen   [PATCH] r/o bind ...
574
575
  	fput(file);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
  	return error;
  }
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
  /*
   * 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...
606
  static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
482928d59   Al Viro   Fix f_flags/f_mod...
607
  					struct file *f,
745ca2475   David Howells   CRED: Pass creden...
608
609
  					int (*open)(struct inode *, struct file *),
  					const struct cred *cred)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
  {
1abf0c718   Al Viro   New kind of open ...
611
  	static const struct file_operations empty_fops = {};
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
  	struct inode *inode;
  	int error;
5300990c0   Al Viro   Sanitize f_flags ...
614
  	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
a1a5b3d93   Peter Staubach   [PATCH] open retu...
615
  				FMODE_PREAD | FMODE_PWRITE;
1abf0c718   Al Viro   New kind of open ...
616
617
618
  
  	if (unlikely(f->f_flags & O_PATH))
  		f->f_mode = FMODE_PATH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
  	inode = dentry->d_inode;
  	if (f->f_mode & FMODE_WRITE) {
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
621
  		error = __get_file_write_access(inode, mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
  		if (error)
  			goto cleanup_file;
ad775f5a8   Dave Hansen   [PATCH] r/o bind ...
624
625
  		if (!special_file(inode->i_mode))
  			file_take_write(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
  	}
  
  	f->f_mapping = inode->i_mapping;
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
629
630
  	f->f_path.dentry = dentry;
  	f->f_path.mnt = mnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
  	f->f_pos = 0;
ee2ffa0df   Nick Piggin   fs: cleanup files...
632
  	file_sb_list_add(f, inode->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633

1abf0c718   Al Viro   New kind of open ...
634
635
636
637
638
639
  	if (unlikely(f->f_mode & FMODE_PATH)) {
  		f->f_op = &empty_fops;
  		return f;
  	}
  
  	f->f_op = fops_get(inode->i_fop);
745ca2475   David Howells   CRED: Pass creden...
640
  	error = security_dentry_open(f, cred);
788e7dd4c   Yuichi Nakamura   SELinux: Improve ...
641
642
  	if (error)
  		goto cleanup_all;
f3c7691e8   J. Bruce Fields   leases: fix write...
643
644
645
  	error = break_lease(inode, f->f_flags);
  	if (error)
  		goto cleanup_all;
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
646
647
648
649
  	if (!open && f->f_op)
  		open = f->f_op->open;
  	if (open) {
  		error = open(inode, f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
652
  		if (error)
  			goto cleanup_all;
  	}
890275b5e   Mimi Zohar   IMA: maintain i_r...
653
654
  	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
  		i_readcount_inc(inode);
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
655

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
660
661
  	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...
662
663
  		if (!f->f_mapping->a_ops ||
  		    ((!f->f_mapping->a_ops->direct_IO) &&
70688e4dd   Nick Piggin   xip: support non-...
664
  		    (!f->f_mapping->a_ops->get_xip_mem))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
668
669
670
671
672
673
  			fput(f);
  			f = ERR_PTR(-EINVAL);
  		}
  	}
  
  	return f;
  
  cleanup_all:
  	fops_put(f->f_op);
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
674
  	if (f->f_mode & FMODE_WRITE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
  		put_write_access(inode);
ad775f5a8   Dave Hansen   [PATCH] r/o bind ...
676
677
678
679
680
681
682
683
  		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 ...
684
  			mnt_drop_write(mnt);
ad775f5a8   Dave Hansen   [PATCH] r/o bind ...
685
  		}
4a3fd211c   Dave Hansen   [PATCH] r/o bind ...
686
  	}
ee2ffa0df   Nick Piggin   fs: cleanup files...
687
  	file_sb_list_del(f);
0f7fc9e4d   Josef "Jeff" Sipek   [PATCH] VFS: chan...
688
689
  	f->f_path.dentry = NULL;
  	f->f_path.mnt = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
  cleanup_file:
  	put_filp(f);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
695
  	dput(dentry);
  	mntput(mnt);
  	return ERR_PTR(error);
  }
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
696
697
698
699
700
701
702
703
704
705
  /**
   * 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...
706
707
708
709
   * 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...
710
711
712
713
714
715
716
717
   * 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...
718
  	const struct cred *cred = current_cred();
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
719
720
721
722
  	if (IS_ERR(nd->intent.open.file))
  		goto out;
  	if (IS_ERR(dentry))
  		goto out_err;
4ac913785   Jan Blunck   Embed a struct pa...
723
  	nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
724
  					     nd->intent.open.file,
745ca2475   David Howells   CRED: Pass creden...
725
  					     open, cred);
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
726
727
728
729
  out:
  	return nd->intent.open.file;
  out_err:
  	release_open_intent(nd);
5a9a43646   Konstantin Khlebnikov   vfs: use ERR_CAST...
730
  	nd->intent.open.file = ERR_CAST(dentry);
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
731
732
733
734
735
736
737
738
739
740
741
  	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
   */
482928d59   Al Viro   Fix f_flags/f_mod...
742
  struct file *nameidata_to_filp(struct nameidata *nd)
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
743
  {
745ca2475   David Howells   CRED: Pass creden...
744
  	const struct cred *cred = current_cred();
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
745
746
747
748
  	struct file *filp;
  
  	/* Pick up the filp from the open intent */
  	filp = nd->intent.open.file;
2dab59744   Linus Torvalds   Fix possible filp...
749
  	nd->intent.open.file = NULL;
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
750
  	/* Has the filesystem initialised the file for us? */
d893f1bc2   Al Viro   fix open/umount race
751
752
  	if (filp->f_path.dentry == NULL) {
  		path_get(&nd->path);
482928d59   Al Viro   Fix f_flags/f_mod...
753
  		filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp,
745ca2475   David Howells   CRED: Pass creden...
754
  				     NULL, cred);
d893f1bc2   Al Viro   fix open/umount race
755
  	}
834f2a4a1   Trond Myklebust   VFS: Allow the fi...
756
757
  	return filp;
  }
6fdcc2162   Peter Staubach   [PATCH] memory le...
758
759
760
761
  /*
   * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
   * error.
   */
745ca2475   David Howells   CRED: Pass creden...
762
763
  struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
  			 const struct cred *cred)
a1a5b3d93   Peter Staubach   [PATCH] open retu...
764
765
766
  {
  	int error;
  	struct file *f;
e0e817392   David Howells   CRED: Add some co...
767
  	validate_creds(cred);
c212f9aaf   Tetsuo Handa   fs: Use BUG_ON(!m...
768
769
  	/* We must always pass in a valid mount pointer. */
  	BUG_ON(!mnt);
322ee5b36   Christoph Hellwig   [PATCH] check for...
770

a1a5b3d93   Peter Staubach   [PATCH] open retu...
771
772
  	error = -ENFILE;
  	f = get_empty_filp();
6fdcc2162   Peter Staubach   [PATCH] memory le...
773
774
775
  	if (f == NULL) {
  		dput(dentry);
  		mntput(mnt);
a1a5b3d93   Peter Staubach   [PATCH] open retu...
776
  		return ERR_PTR(error);
6fdcc2162   Peter Staubach   [PATCH] memory le...
777
  	}
a1a5b3d93   Peter Staubach   [PATCH] open retu...
778

482928d59   Al Viro   Fix f_flags/f_mod...
779
780
  	f->f_flags = flags;
  	return __dentry_open(dentry, mnt, f, NULL, cred);
a1a5b3d93   Peter Staubach   [PATCH] open retu...
781
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
  EXPORT_SYMBOL(dentry_open);
b01ec0ef6   Matt Mackall   [PATCH] tiny: Uni...
783
  static void __put_unused_fd(struct files_struct *files, unsigned int fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  {
badf16621   Dipankar Sarma   [PATCH] files: br...
785
786
  	struct fdtable *fdt = files_fdtable(files);
  	__FD_CLR(fd, fdt->open_fds);
0c9e63fd3   Eric Dumazet   [PATCH] Shrinks s...
787
788
  	if (fd < files->next_fd)
  		files->next_fd = fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  }
fc9b52cd8   Harvey Harrison   fs: remove fastca...
790
  void put_unused_fd(unsigned int fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
793
794
795
796
797
798
799
800
  {
  	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 ...
801
   * Install a file pointer in the fd array.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
804
805
806
807
808
809
810
811
   *
   * 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...
812
  void fd_install(unsigned int fd, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
814
  {
  	struct files_struct *files = current->files;
badf16621   Dipankar Sarma   [PATCH] files: br...
815
  	struct fdtable *fdt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
816
  	spin_lock(&files->file_lock);
badf16621   Dipankar Sarma   [PATCH] files: br...
817
  	fdt = files_fdtable(files);
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
818
819
  	BUG_ON(fdt->fd[fd] != NULL);
  	rcu_assign_pointer(fdt->fd[fd], file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
823
  	spin_unlock(&files->file_lock);
  }
  
  EXPORT_SYMBOL(fd_install);
a218d0fdc   Al Viro   switch open and m...
824
  static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
47c805dc2   Al Viro   switch do_filp_op...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  {
  	int lookup_flags = 0;
  	int acc_mode;
  
  	if (!(flags & O_CREAT))
  		mode = 0;
  	op->mode = mode;
  
  	/* Must never be set by userspace */
  	flags &= ~FMODE_NONOTIFY;
  
  	/*
  	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
  	 * check for O_DSYNC if the need any syncing at all we enforce it's
  	 * always set instead of having to deal with possibly weird behaviour
  	 * for malicious applications setting only __O_SYNC.
  	 */
  	if (flags & __O_SYNC)
  		flags |= O_DSYNC;
1abf0c718   Al Viro   New kind of open ...
844
845
846
847
848
849
850
851
852
853
  	/*
  	 * If we have O_PATH in the open flag. Then we
  	 * cannot have anything other than the below set of flags
  	 */
  	if (flags & O_PATH) {
  		flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
  		acc_mode = 0;
  	} else {
  		acc_mode = MAY_OPEN | ACC_MODE(flags);
  	}
47c805dc2   Al Viro   switch do_filp_op...
854

1abf0c718   Al Viro   New kind of open ...
855
  	op->open_flag = flags;
47c805dc2   Al Viro   switch do_filp_op...
856
857
858
859
860
861
862
863
864
865
866
  
  	/* O_TRUNC implies we need access checks for write permissions */
  	if (flags & O_TRUNC)
  		acc_mode |= MAY_WRITE;
  
  	/* Allow the LSM permission hook to distinguish append
  	   access from general write access. */
  	if (flags & O_APPEND)
  		acc_mode |= MAY_APPEND;
  
  	op->acc_mode = acc_mode;
1abf0c718   Al Viro   New kind of open ...
867
  	op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN;
47c805dc2   Al Viro   switch do_filp_op...
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
  	if (flags & O_CREAT) {
  		op->intent |= LOOKUP_CREATE;
  		if (flags & O_EXCL)
  			op->intent |= LOOKUP_EXCL;
  	}
  
  	if (flags & O_DIRECTORY)
  		lookup_flags |= LOOKUP_DIRECTORY;
  	if (!(flags & O_NOFOLLOW))
  		lookup_flags |= LOOKUP_FOLLOW;
  	return lookup_flags;
  }
  
  /**
   * filp_open - open file and return file pointer
   *
   * @filename:	path to open
   * @flags:	open flags as per the open(2) second argument
   * @mode:	mode for the new file if O_CREAT is set, else ignored
   *
   * This is the helper to open a file from kernelspace if you really
   * have to.  But in generally you should not do this, so please move
   * along, nothing to see here..
   */
a218d0fdc   Al Viro   switch open and m...
892
  struct file *filp_open(const char *filename, int flags, umode_t mode)
47c805dc2   Al Viro   switch do_filp_op...
893
894
895
896
897
898
  {
  	struct open_flags op;
  	int lookup = build_open_flags(flags, mode, &op);
  	return do_filp_open(AT_FDCWD, filename, &op, lookup);
  }
  EXPORT_SYMBOL(filp_open);
73d049a40   Al Viro   open-style analog...
899
900
901
902
903
904
905
906
907
908
909
910
911
  struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
  			    const char *filename, int flags)
  {
  	struct open_flags op;
  	int lookup = build_open_flags(flags, 0, &op);
  	if (flags & O_CREAT)
  		return ERR_PTR(-EINVAL);
  	if (!filename && (flags & O_DIRECTORY))
  		if (!dentry->d_inode->i_op->lookup)
  			return ERR_PTR(-ENOTDIR);
  	return do_file_open_root(dentry, mnt, filename, &op, lookup);
  }
  EXPORT_SYMBOL(file_open_root);
a218d0fdc   Al Viro   switch open and m...
912
  long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
  {
47c805dc2   Al Viro   switch do_filp_op...
914
915
  	struct open_flags op;
  	int lookup = build_open_flags(flags, mode, &op);
e922efc34   Miklos Szeredi   [PATCH] remove du...
916
917
  	char *tmp = getname(filename);
  	int fd = PTR_ERR(tmp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
918

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
  	if (!IS_ERR(tmp)) {
f23513e8d   Ulrich Drepper   Introduce O_CLOEXEC
920
  		fd = get_unused_fd_flags(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
  		if (fd >= 0) {
47c805dc2   Al Viro   switch do_filp_op...
922
  			struct file *f = do_filp_open(dfd, tmp, &op, lookup);
fed2fc18a   Telemaque Ndizihiwe   [PATCH] sys_open(...
923
924
925
926
  			if (IS_ERR(f)) {
  				put_unused_fd(fd);
  				fd = PTR_ERR(f);
  			} else {
2a12a9d78   Eric Paris   fsnotify: pass a ...
927
  				fsnotify_open(f);
fed2fc18a   Telemaque Ndizihiwe   [PATCH] sys_open(...
928
929
  				fd_install(fd, f);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
  		putname(tmp);
  	}
  	return fd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
  }
e922efc34   Miklos Szeredi   [PATCH] remove du...
935

a218d0fdc   Al Viro   switch open and m...
936
  SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
e922efc34   Miklos Szeredi   [PATCH] remove du...
937
  {
385910f2b   Linus Torvalds   x86: be careful a...
938
  	long ret;
e922efc34   Miklos Szeredi   [PATCH] remove du...
939
940
  	if (force_o_largefile())
  		flags |= O_LARGEFILE;
385910f2b   Linus Torvalds   x86: be careful a...
941
942
  	ret = do_sys_open(AT_FDCWD, filename, flags, mode);
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
943
  	asmlinkage_protect(3, ret, filename, flags, mode);
385910f2b   Linus Torvalds   x86: be careful a...
944
  	return ret;
e922efc34   Miklos Szeredi   [PATCH] remove du...
945
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
946

6559eed8c   Heiko Carstens   [CVE-2009-0029] S...
947
  SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
a218d0fdc   Al Viro   switch open and m...
948
  		umode_t, mode)
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
949
  {
385910f2b   Linus Torvalds   x86: be careful a...
950
  	long ret;
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
951
952
  	if (force_o_largefile())
  		flags |= O_LARGEFILE;
385910f2b   Linus Torvalds   x86: be careful a...
953
954
  	ret = do_sys_open(dfd, filename, flags, mode);
  	/* avoid REGPARM breakage on x86: */
54a015104   Roland McGrath   asmlinkage_protec...
955
  	asmlinkage_protect(4, ret, dfd, filename, flags, mode);
385910f2b   Linus Torvalds   x86: be careful a...
956
  	return ret;
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
957
  }
5590ff0d5   Ulrich Drepper   [PATCH] vfs: *at ...
958

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959
960
961
962
963
964
  #ifndef __alpha__
  
  /*
   * For backward compatibility?  Maybe this should be moved
   * into arch/i386 instead?
   */
a218d0fdc   Al Viro   switch open and m...
965
  SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966
967
968
969
970
971
972
973
974
975
976
977
  {
  	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_...
978
  	int retval = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
979
980
981
982
  
  	if (!file_count(filp)) {
  		printk(KERN_ERR "VFS: Close: file count is 0
  ");
45778ca81   Christoph Lameter   [PATCH] Remove f_...
983
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
  	}
45778ca81   Christoph Lameter   [PATCH] Remove f_...
985
  	if (filp->f_op && filp->f_op->flush)
75e1fcc0b   Miklos Szeredi   [PATCH] vfs: add ...
986
  		retval = filp->f_op->flush(filp, id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987

1abf0c718   Al Viro   New kind of open ...
988
989
990
991
  	if (likely(!(filp->f_mode & FMODE_PATH))) {
  		dnotify_flush(filp, id);
  		locks_remove_posix(filp, id);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
992
993
994
995
996
997
998
999
1000
1001
1002
  	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...
1003
  SYSCALL_DEFINE1(close, unsigned int, fd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1004
1005
1006
  {
  	struct file * filp;
  	struct files_struct *files = current->files;
badf16621   Dipankar Sarma   [PATCH] files: br...
1007
  	struct fdtable *fdt;
ee731f4f7   Ernie Petrides   [PATCH] fix wrong...
1008
  	int retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1009
1010
  
  	spin_lock(&files->file_lock);
badf16621   Dipankar Sarma   [PATCH] files: br...
1011
1012
  	fdt = files_fdtable(files);
  	if (fd >= fdt->max_fds)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1013
  		goto out_unlock;
badf16621   Dipankar Sarma   [PATCH] files: br...
1014
  	filp = fdt->fd[fd];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
  	if (!filp)
  		goto out_unlock;
ab2af1f50   Dipankar Sarma   [PATCH] files: fi...
1017
  	rcu_assign_pointer(fdt->fd[fd], NULL);
badf16621   Dipankar Sarma   [PATCH] files: br...
1018
  	FD_CLR(fd, fdt->close_on_exec);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1019
1020
  	__put_unused_fd(files, fd);
  	spin_unlock(&files->file_lock);
ee731f4f7   Ernie Petrides   [PATCH] fix wrong...
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
  	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
1031
1032
1033
1034
1035
  
  out_unlock:
  	spin_unlock(&files->file_lock);
  	return -EBADF;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
1037
1038
1039
1040
1041
  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...
1042
  SYSCALL_DEFINE0(vhangup)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1043
1044
  {
  	if (capable(CAP_SYS_TTY_CONFIG)) {
2cb5998b5   Alan Cox   tty: the vhangup ...
1045
  		tty_vhangup_self();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
  		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...
1060
  		return -EOVERFLOW;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
1063
1064
1065
1066
1067
  	return 0;
  }
  
  EXPORT_SYMBOL(generic_file_open);
  
  /*
   * This is used by subsystems that don't want seekable
06b1e104b   Dmitry Torokhov   vfs: clarify that...
1068
1069
1070
   * file descriptors. The function is not supposed to ever fail, the only
   * reason it returns an 'int' and not 'void' is so that it can be plugged
   * directly into file_operations structure.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1071
1072
1073
1074
1075
1076
1077
1078
   */
  int nonseekable_open(struct inode *inode, struct file *filp)
  {
  	filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
  	return 0;
  }
  
  EXPORT_SYMBOL(nonseekable_open);