Blame view
fs/open.c
28.4 KB
1da177e4c 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 Linux-2.6.12-rc2 |
9 |
#include <linux/file.h> |
9f3acc314 [PATCH] split lin... |
10 |
#include <linux/fdtable.h> |
0eeca2830 [PATCH] inotify |
11 |
#include <linux/fsnotify.h> |
1da177e4c Linux-2.6.12-rc2 |
12 |
#include <linux/module.h> |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 |
#include <linux/tty.h> #include <linux/namei.h> #include <linux/backing-dev.h> |
16f7e0fe2 [PATCH] capable/c... |
16 |
#include <linux/capability.h> |
086f7316f security: filesys... |
17 |
#include <linux/securebits.h> |
1da177e4c Linux-2.6.12-rc2 |
18 19 |
#include <linux/security.h> #include <linux/mount.h> |
5590ff0d5 [PATCH] vfs: *at ... |
20 |
#include <linux/fcntl.h> |
5a0e3ad6a include cleanup: ... |
21 |
#include <linux/slab.h> |
7c0f6ba68 Replace <asm/uacc... |
22 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
23 |
#include <linux/fs.h> |
ef3daeda7 [PATCH] Don't for... |
24 |
#include <linux/personality.h> |
1da177e4c Linux-2.6.12-rc2 |
25 26 |
#include <linux/pagemap.h> #include <linux/syscalls.h> |
ab2af1f50 [PATCH] files: fi... |
27 |
#include <linux/rcupdate.h> |
73241ccca [PATCH] Collect m... |
28 |
#include <linux/audit.h> |
97ac73506 sys_fallocate() i... |
29 |
#include <linux/falloc.h> |
5ad4e53bd Get rid of indire... |
30 |
#include <linux/fs_struct.h> |
b65a9cfc2 Untangling ima me... |
31 |
#include <linux/ima.h> |
2dfc1cae4 inotify: remove i... |
32 |
#include <linux/dnotify.h> |
3f6d078d4 fix compat trunca... |
33 |
#include <linux/compat.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
|
e81e3f4dc fs: move get_empt... |
35 |
#include "internal.h" |
4a30131e7 [PATCH] Fix some ... |
36 37 |
int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
38 |
{ |
939a9421e vfs: allow file t... |
39 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
40 41 42 43 44 45 46 |
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 [PATCH] Fix some ... |
47 |
newattrs.ia_valid = ATTR_SIZE | time_attrs; |
cc4e69dee [PATCH] VFS: pass... |
48 49 50 51 |
if (filp) { newattrs.ia_file = filp; newattrs.ia_valid |= ATTR_FILE; } |
1da177e4c Linux-2.6.12-rc2 |
52 |
|
45f147a1b fs: Call security... |
53 54 55 56 |
/* Remove suid, sgid, and file capabilities on truncate too */ ret = dentry_needs_remove_privs(dentry); if (ret < 0) return ret; |
939a9421e vfs: allow file t... |
57 58 |
if (ret) newattrs.ia_valid |= ret | ATTR_FORCE; |
7b82dc0e6 Remove suid/sgid ... |
59 |
|
5955102c9 wrappers for ->i_... |
60 |
inode_lock(dentry->d_inode); |
27ac0ffea locks: break dele... |
61 62 |
/* Note any delegations or leases have already been broken: */ ret = notify_change(dentry, &newattrs, NULL); |
5955102c9 wrappers for ->i_... |
63 |
inode_unlock(dentry->d_inode); |
939a9421e vfs: allow file t... |
64 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
65 |
} |
7df818b23 constify vfs_trun... |
66 |
long vfs_truncate(const struct path *path, loff_t length) |
1da177e4c Linux-2.6.12-rc2 |
67 |
{ |
2d8f30380 [PATCH] sanitize ... |
68 |
struct inode *inode; |
4d0c5ba2f vfs: do get_write... |
69 |
struct dentry *upperdentry; |
a02de9608 VFS: Make more co... |
70 |
long error; |
1da177e4c Linux-2.6.12-rc2 |
71 |
|
a02de9608 VFS: Make more co... |
72 |
inode = path->dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
73 74 |
/* For directories it's -EISDIR, for other non-regulars - -EINVAL */ |
1da177e4c Linux-2.6.12-rc2 |
75 |
if (S_ISDIR(inode->i_mode)) |
a02de9608 VFS: Make more co... |
76 |
return -EISDIR; |
1da177e4c Linux-2.6.12-rc2 |
77 |
if (!S_ISREG(inode->i_mode)) |
a02de9608 VFS: Make more co... |
78 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
79 |
|
a02de9608 VFS: Make more co... |
80 |
error = mnt_want_write(path->mnt); |
1da177e4c Linux-2.6.12-rc2 |
81 |
if (error) |
a02de9608 VFS: Make more co... |
82 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
83 |
|
256984a83 [PATCH] preparati... |
84 |
error = inode_permission(inode, MAY_WRITE); |
9ac9b8474 [PATCH] r/o bind ... |
85 86 |
if (error) goto mnt_drop_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
87 88 |
error = -EPERM; |
c82e42da8 [patch 1/5] vfs: ... |
89 |
if (IS_APPEND(inode)) |
9ac9b8474 [PATCH] r/o bind ... |
90 |
goto mnt_drop_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
91 |
|
4d0c5ba2f vfs: do get_write... |
92 93 94 95 96 |
/* * If this is an overlayfs then do as if opening the file so we get * write access on the upper inode, not on the overlay inode. For * non-overlay filesystems d_real() is an identity function. */ |
495e64293 vfs: add flags to... |
97 |
upperdentry = d_real(path->dentry, NULL, O_WRONLY, 0); |
4d0c5ba2f vfs: do get_write... |
98 99 100 101 102 |
error = PTR_ERR(upperdentry); if (IS_ERR(upperdentry)) goto mnt_drop_write_and_out; error = get_write_access(upperdentry->d_inode); |
1da177e4c Linux-2.6.12-rc2 |
103 |
if (error) |
9ac9b8474 [PATCH] r/o bind ... |
104 |
goto mnt_drop_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
105 |
|
9700382c3 VFS: fix a race i... |
106 107 108 109 |
/* * Make sure that there are no leases. get_write_access() protects * against the truncate racing with a lease-granting setlease(). */ |
8737c9305 Switch may_open()... |
110 |
error = break_lease(inode, O_WRONLY); |
1da177e4c Linux-2.6.12-rc2 |
111 |
if (error) |
9700382c3 VFS: fix a race i... |
112 |
goto put_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
113 114 |
error = locks_verify_truncate(inode, NULL, length); |
be6d3e56a introduce new LSM... |
115 |
if (!error) |
a02de9608 VFS: Make more co... |
116 |
error = security_path_truncate(path); |
907f4554e dquot: move dquot... |
117 |
if (!error) |
a02de9608 VFS: Make more co... |
118 |
error = do_truncate(path->dentry, length, 0, NULL); |
1da177e4c Linux-2.6.12-rc2 |
119 |
|
9700382c3 VFS: fix a race i... |
120 |
put_write_and_out: |
4d0c5ba2f vfs: do get_write... |
121 |
put_write_access(upperdentry->d_inode); |
9ac9b8474 [PATCH] r/o bind ... |
122 |
mnt_drop_write_and_out: |
a02de9608 VFS: Make more co... |
123 |
mnt_drop_write(path->mnt); |
1da177e4c Linux-2.6.12-rc2 |
124 125 126 |
out: return error; } |
a02de9608 VFS: Make more co... |
127 128 129 130 |
EXPORT_SYMBOL_GPL(vfs_truncate); static long do_sys_truncate(const char __user *pathname, loff_t length) { |
48f7530d3 vfs: have do_sys_... |
131 |
unsigned int lookup_flags = LOOKUP_FOLLOW; |
a02de9608 VFS: Make more co... |
132 133 134 135 136 |
struct path path; int error; if (length < 0) /* sorry, but loff_t says... */ return -EINVAL; |
48f7530d3 vfs: have do_sys_... |
137 138 |
retry: error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); |
a02de9608 VFS: Make more co... |
139 140 141 142 |
if (!error) { error = vfs_truncate(&path, length); path_put(&path); } |
48f7530d3 vfs: have do_sys_... |
143 144 145 146 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
a02de9608 VFS: Make more co... |
147 148 |
return error; } |
1da177e4c Linux-2.6.12-rc2 |
149 |
|
4fd8da8d6 fs: change sys_tr... |
150 |
SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) |
1da177e4c Linux-2.6.12-rc2 |
151 |
{ |
4fd8da8d6 fs: change sys_tr... |
152 |
return do_sys_truncate(path, length); |
1da177e4c Linux-2.6.12-rc2 |
153 |
} |
3f6d078d4 fix compat trunca... |
154 155 156 157 158 159 |
#ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(truncate, const char __user *, path, compat_off_t, length) { return do_sys_truncate(path, length); } #endif |
b01ec0ef6 [PATCH] tiny: Uni... |
160 |
static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) |
1da177e4c Linux-2.6.12-rc2 |
161 |
{ |
bf2965d5b switch ftruncate(... |
162 |
struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
163 |
struct dentry *dentry; |
2903ff019 switch simple cas... |
164 |
struct fd f; |
1da177e4c Linux-2.6.12-rc2 |
165 166 167 168 169 170 |
int error; error = -EINVAL; if (length < 0) goto out; error = -EBADF; |
2903ff019 switch simple cas... |
171 172 |
f = fdget(fd); if (!f.file) |
1da177e4c Linux-2.6.12-rc2 |
173 174 175 |
goto out; /* explicitly opened as large or we are on 64-bit box */ |
2903ff019 switch simple cas... |
176 |
if (f.file->f_flags & O_LARGEFILE) |
1da177e4c Linux-2.6.12-rc2 |
177 |
small = 0; |
2903ff019 switch simple cas... |
178 |
dentry = f.file->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
179 180 |
inode = dentry->d_inode; error = -EINVAL; |
2903ff019 switch simple cas... |
181 |
if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE)) |
1da177e4c Linux-2.6.12-rc2 |
182 183 184 185 186 187 188 189 |
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; |
78757af65 vfs: ftruncate ch... |
190 191 |
/* Check IS_APPEND on real upper inode */ if (IS_APPEND(file_inode(f.file))) |
1da177e4c Linux-2.6.12-rc2 |
192 |
goto out_putf; |
14da92001 fs: Protect write... |
193 |
sb_start_write(inode->i_sb); |
2903ff019 switch simple cas... |
194 |
error = locks_verify_truncate(inode, f.file, length); |
1da177e4c Linux-2.6.12-rc2 |
195 |
if (!error) |
2903ff019 switch simple cas... |
196 |
error = security_path_truncate(&f.file->f_path); |
be6d3e56a introduce new LSM... |
197 |
if (!error) |
2903ff019 switch simple cas... |
198 |
error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, f.file); |
14da92001 fs: Protect write... |
199 |
sb_end_write(inode->i_sb); |
1da177e4c Linux-2.6.12-rc2 |
200 |
out_putf: |
2903ff019 switch simple cas... |
201 |
fdput(f); |
1da177e4c Linux-2.6.12-rc2 |
202 203 204 |
out: return error; } |
bdc480e3b [CVE-2009-0029] S... |
205 |
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length) |
1da177e4c Linux-2.6.12-rc2 |
206 |
{ |
2cf096668 make SYSCALL_DEFI... |
207 |
return do_sys_ftruncate(fd, length, 1); |
1da177e4c Linux-2.6.12-rc2 |
208 |
} |
3f6d078d4 fix compat trunca... |
209 210 211 212 213 214 |
#ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_ulong_t, length) { return do_sys_ftruncate(fd, length, 1); } #endif |
1da177e4c Linux-2.6.12-rc2 |
215 216 |
/* LFS versions of truncate are only needed on 32 bit machines */ #if BITS_PER_LONG == 32 |
4a0fd5bf0 teach SYSCALL_DEF... |
217 |
SYSCALL_DEFINE2(truncate64, const char __user *, path, loff_t, length) |
1da177e4c Linux-2.6.12-rc2 |
218 219 220 |
{ return do_sys_truncate(path, length); } |
4a0fd5bf0 teach SYSCALL_DEF... |
221 |
SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length) |
1da177e4c Linux-2.6.12-rc2 |
222 |
{ |
2cf096668 make SYSCALL_DEFI... |
223 |
return do_sys_ftruncate(fd, length, 0); |
1da177e4c Linux-2.6.12-rc2 |
224 |
} |
6673e0c3f [CVE-2009-0029] S... |
225 |
#endif /* BITS_PER_LONG == 32 */ |
1da177e4c Linux-2.6.12-rc2 |
226 |
|
3e63cbb1e fs: Add new pre-a... |
227 |
|
72c72bdf7 VFS: Rename do_fa... |
228 |
int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) |
97ac73506 sys_fallocate() i... |
229 |
{ |
496ad9aa8 new helper: file_... |
230 |
struct inode *inode = file_inode(file); |
3e63cbb1e fs: Add new pre-a... |
231 |
long ret; |
97ac73506 sys_fallocate() i... |
232 233 |
if (offset < 0 || len <= 0) |
3e63cbb1e fs: Add new pre-a... |
234 |
return -EINVAL; |
97ac73506 sys_fallocate() i... |
235 236 |
/* Return error if mode is not supported */ |
dd46c7877 fs: Add support F... |
237 |
if (mode & ~FALLOC_FL_SUPPORTED_MASK) |
409332b65 fs: Introduce FAL... |
238 239 240 241 242 |
return -EOPNOTSUPP; /* Punch hole and zero range are mutually exclusive */ if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) == (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) |
79124f18b fs: add hole punc... |
243 244 245 246 247 |
return -EOPNOTSUPP; /* Punch hole must have keep size set */ if ((mode & FALLOC_FL_PUNCH_HOLE) && !(mode & FALLOC_FL_KEEP_SIZE)) |
3e63cbb1e fs: Add new pre-a... |
248 |
return -EOPNOTSUPP; |
97ac73506 sys_fallocate() i... |
249 |
|
00f5e6199 fs: Add new flag(... |
250 251 252 253 |
/* Collapse range should only be used exclusively. */ if ((mode & FALLOC_FL_COLLAPSE_RANGE) && (mode & ~FALLOC_FL_COLLAPSE_RANGE)) return -EINVAL; |
dd46c7877 fs: Add support F... |
254 255 256 257 |
/* Insert range should only be used exclusively. */ if ((mode & FALLOC_FL_INSERT_RANGE) && (mode & ~FALLOC_FL_INSERT_RANGE)) return -EINVAL; |
71be6b494 vfs: add a FALLOC... |
258 259 260 261 |
/* Unshare range should only be used with allocate mode. */ if ((mode & FALLOC_FL_UNSHARE_RANGE) && (mode & ~(FALLOC_FL_UNSHARE_RANGE | FALLOC_FL_KEEP_SIZE))) return -EINVAL; |
97ac73506 sys_fallocate() i... |
262 |
if (!(file->f_mode & FMODE_WRITE)) |
3e63cbb1e fs: Add new pre-a... |
263 |
return -EBADF; |
1ca551c6c Check for immutab... |
264 |
|
00f5e6199 fs: Add new flag(... |
265 |
/* |
8fc61d926 fs: prevent doing... |
266 |
* We can only allow pure fallocate on append only files |
00f5e6199 fs: Add new flag(... |
267 |
*/ |
8fc61d926 fs: prevent doing... |
268 |
if ((mode & ~FALLOC_FL_KEEP_SIZE) && IS_APPEND(inode)) |
1ca551c6c Check for immutab... |
269 270 271 272 |
return -EPERM; if (IS_IMMUTABLE(inode)) return -EPERM; |
97ac73506 sys_fallocate() i... |
273 |
/* |
6d2b6170c vfs: fix check fo... |
274 |
* We cannot allow any fallocate operation on an active swapfile |
0790b31b6 fs: disallow all ... |
275 276 |
*/ if (IS_SWAPFILE(inode)) |
6d2b6170c vfs: fix check fo... |
277 |
return -ETXTBSY; |
0790b31b6 fs: disallow all ... |
278 279 |
/* |
97ac73506 sys_fallocate() i... |
280 281 282 283 284 |
* 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 fs: Add new pre-a... |
285 |
return ret; |
97ac73506 sys_fallocate() i... |
286 |
|
97ac73506 sys_fallocate() i... |
287 |
if (S_ISFIFO(inode->i_mode)) |
3e63cbb1e fs: Add new pre-a... |
288 |
return -ESPIPE; |
97ac73506 sys_fallocate() i... |
289 |
|
9e79b1326 vfs: deny falloca... |
290 291 292 293 |
if (S_ISDIR(inode->i_mode)) return -EISDIR; if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) |
3e63cbb1e fs: Add new pre-a... |
294 |
return -ENODEV; |
97ac73506 sys_fallocate() i... |
295 |
|
97ac73506 sys_fallocate() i... |
296 297 |
/* Check for wrap through zero too */ if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) |
3e63cbb1e fs: Add new pre-a... |
298 |
return -EFBIG; |
97ac73506 sys_fallocate() i... |
299 |
|
2fe17c107 fallocate should ... |
300 |
if (!file->f_op->fallocate) |
3e63cbb1e fs: Add new pre-a... |
301 |
return -EOPNOTSUPP; |
97ac73506 sys_fallocate() i... |
302 |
|
bfe219d37 vfs: wrap write f... |
303 |
file_start_write(file); |
14da92001 fs: Protect write... |
304 |
ret = file->f_op->fallocate(file, mode, offset, len); |
820c12d5d fallocate: create... |
305 306 307 308 309 310 311 312 313 314 |
/* * Create inotify and fanotify events. * * To keep the logic simple always create events if fallocate succeeds. * This implies that events are even created if the file size remains * unchanged, e.g. when using flag FALLOC_FL_KEEP_SIZE. */ if (ret == 0) fsnotify_modify(file); |
bfe219d37 vfs: wrap write f... |
315 |
file_end_write(file); |
14da92001 fs: Protect write... |
316 |
return ret; |
3e63cbb1e fs: Add new pre-a... |
317 |
} |
72c72bdf7 VFS: Rename do_fa... |
318 |
EXPORT_SYMBOL_GPL(vfs_fallocate); |
3e63cbb1e fs: Add new pre-a... |
319 |
|
4a0fd5bf0 teach SYSCALL_DEF... |
320 |
SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) |
3e63cbb1e fs: Add new pre-a... |
321 |
{ |
2903ff019 switch simple cas... |
322 |
struct fd f = fdget(fd); |
3e63cbb1e fs: Add new pre-a... |
323 |
int error = -EBADF; |
2903ff019 switch simple cas... |
324 |
if (f.file) { |
72c72bdf7 VFS: Rename do_fa... |
325 |
error = vfs_fallocate(f.file, mode, offset, len); |
2903ff019 switch simple cas... |
326 |
fdput(f); |
3e63cbb1e fs: Add new pre-a... |
327 |
} |
3e63cbb1e fs: Add new pre-a... |
328 |
return error; |
97ac73506 sys_fallocate() i... |
329 |
} |
3e63cbb1e fs: Add new pre-a... |
330 |
|
1da177e4c Linux-2.6.12-rc2 |
331 332 333 334 335 |
/* * 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 [CVE-2009-0029] S... |
336 |
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) |
1da177e4c Linux-2.6.12-rc2 |
337 |
{ |
d84f4f992 CRED: Inaugurate ... |
338 339 |
const struct cred *old_cred; struct cred *override_cred; |
2d8f30380 [PATCH] sanitize ... |
340 |
struct path path; |
256984a83 [PATCH] preparati... |
341 |
struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
342 |
int res; |
87fa55952 vfs: have faccess... |
343 |
unsigned int lookup_flags = LOOKUP_FOLLOW; |
1da177e4c Linux-2.6.12-rc2 |
344 345 346 |
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; |
d84f4f992 CRED: Inaugurate ... |
347 348 349 |
override_cred = prepare_creds(); if (!override_cred) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
350 |
|
d84f4f992 CRED: Inaugurate ... |
351 352 |
override_cred->fsuid = override_cred->uid; override_cred->fsgid = override_cred->gid; |
1da177e4c Linux-2.6.12-rc2 |
353 |
|
086f7316f security: filesys... |
354 |
if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
1cdcbec1a CRED: Neuter sys_... |
355 |
/* Clear the capabilities if we switch to a non-root user */ |
18815a180 userns: Convert c... |
356 357 |
kuid_t root_uid = make_kuid(override_cred->user_ns, 0); if (!uid_eq(override_cred->uid, root_uid)) |
d84f4f992 CRED: Inaugurate ... |
358 |
cap_clear(override_cred->cap_effective); |
086f7316f security: filesys... |
359 |
else |
d84f4f992 CRED: Inaugurate ... |
360 361 |
override_cred->cap_effective = override_cred->cap_permitted; |
086f7316f security: filesys... |
362 |
} |
1da177e4c Linux-2.6.12-rc2 |
363 |
|
d84f4f992 CRED: Inaugurate ... |
364 |
old_cred = override_creds(override_cred); |
87fa55952 vfs: have faccess... |
365 366 |
retry: res = user_path_at(dfd, filename, lookup_flags, &path); |
6902d925d [PATCH] r/o bind ... |
367 368 |
if (res) goto out; |
63afdfc78 VFS: Handle lower... |
369 |
inode = d_backing_inode(path.dentry); |
256984a83 [PATCH] preparati... |
370 371 |
if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { |
30524472c [PATCH] take noex... |
372 373 374 375 376 |
/* * MAY_EXEC on regular files is denied if the fs is mounted * with the "noexec" flag. */ res = -EACCES; |
90f8572b0 vfs: Commit to ne... |
377 |
if (path_noexec(&path)) |
30524472c [PATCH] take noex... |
378 379 |
goto out_path_release; } |
256984a83 [PATCH] preparati... |
380 |
res = inode_permission(inode, mode | MAY_ACCESS); |
6902d925d [PATCH] r/o bind ... |
381 |
/* SuS v2 requires we report a read only fs too */ |
256984a83 [PATCH] preparati... |
382 |
if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) |
6902d925d [PATCH] r/o bind ... |
383 |
goto out_path_release; |
2f676cbc0 [PATCH] r/o bind ... |
384 385 386 387 388 389 390 391 392 393 |
/* * 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 [PATCH] sanitize ... |
394 |
if (__mnt_is_readonly(path.mnt)) |
6902d925d [PATCH] r/o bind ... |
395 |
res = -EROFS; |
1da177e4c Linux-2.6.12-rc2 |
396 |
|
6902d925d [PATCH] r/o bind ... |
397 |
out_path_release: |
2d8f30380 [PATCH] sanitize ... |
398 |
path_put(&path); |
87fa55952 vfs: have faccess... |
399 400 401 402 |
if (retry_estale(res, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
6902d925d [PATCH] r/o bind ... |
403 |
out: |
d84f4f992 CRED: Inaugurate ... |
404 405 |
revert_creds(old_cred); put_cred(override_cred); |
1da177e4c Linux-2.6.12-rc2 |
406 407 |
return res; } |
ca013e945 [CVE-2009-0029] S... |
408 |
SYSCALL_DEFINE2(access, const char __user *, filename, int, mode) |
5590ff0d5 [PATCH] vfs: *at ... |
409 410 411 |
{ return sys_faccessat(AT_FDCWD, filename, mode); } |
3cdad4288 [CVE-2009-0029] S... |
412 |
SYSCALL_DEFINE1(chdir, const char __user *, filename) |
1da177e4c Linux-2.6.12-rc2 |
413 |
{ |
2d8f30380 [PATCH] sanitize ... |
414 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
415 |
int error; |
0291c0a55 vfs: have chdir r... |
416 417 418 |
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; retry: error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); |
1da177e4c Linux-2.6.12-rc2 |
419 420 |
if (error) goto out; |
9cfcac810 vfs: re-introduce... |
421 |
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); |
1da177e4c Linux-2.6.12-rc2 |
422 423 |
if (error) goto dput_and_out; |
2d8f30380 [PATCH] sanitize ... |
424 |
set_fs_pwd(current->fs, &path); |
1da177e4c Linux-2.6.12-rc2 |
425 426 |
dput_and_out: |
2d8f30380 [PATCH] sanitize ... |
427 |
path_put(&path); |
0291c0a55 vfs: have chdir r... |
428 429 430 431 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
1da177e4c Linux-2.6.12-rc2 |
432 433 434 |
out: return error; } |
3cdad4288 [CVE-2009-0029] S... |
435 |
SYSCALL_DEFINE1(fchdir, unsigned int, fd) |
1da177e4c Linux-2.6.12-rc2 |
436 |
{ |
2903ff019 switch simple cas... |
437 |
struct fd f = fdget_raw(fd); |
159b09562 make sure that fc... |
438 |
int error; |
1da177e4c Linux-2.6.12-rc2 |
439 440 |
error = -EBADF; |
2903ff019 switch simple cas... |
441 |
if (!f.file) |
1da177e4c Linux-2.6.12-rc2 |
442 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
443 |
error = -ENOTDIR; |
159b09562 make sure that fc... |
444 |
if (!d_can_lookup(f.file->f_path.dentry)) |
1da177e4c Linux-2.6.12-rc2 |
445 |
goto out_putf; |
159b09562 make sure that fc... |
446 |
error = inode_permission(file_inode(f.file), MAY_EXEC | MAY_CHDIR); |
1da177e4c Linux-2.6.12-rc2 |
447 |
if (!error) |
2903ff019 switch simple cas... |
448 |
set_fs_pwd(current->fs, &f.file->f_path); |
1da177e4c Linux-2.6.12-rc2 |
449 |
out_putf: |
2903ff019 switch simple cas... |
450 |
fdput(f); |
1da177e4c Linux-2.6.12-rc2 |
451 452 453 |
out: return error; } |
3480b2574 [CVE-2009-0029] S... |
454 |
SYSCALL_DEFINE1(chroot, const char __user *, filename) |
1da177e4c Linux-2.6.12-rc2 |
455 |
{ |
2d8f30380 [PATCH] sanitize ... |
456 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
457 |
int error; |
2771261ec vfs: have chroot ... |
458 459 460 |
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; retry: error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); |
1da177e4c Linux-2.6.12-rc2 |
461 462 |
if (error) goto out; |
9cfcac810 vfs: re-introduce... |
463 |
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); |
1da177e4c Linux-2.6.12-rc2 |
464 465 466 467 |
if (error) goto dput_and_out; error = -EPERM; |
c7b96acf1 userns: Kill nso... |
468 |
if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT)) |
1da177e4c Linux-2.6.12-rc2 |
469 |
goto dput_and_out; |
8b8efb440 LSM: Add security... |
470 471 472 |
error = security_path_chroot(&path); if (error) goto dput_and_out; |
1da177e4c Linux-2.6.12-rc2 |
473 |
|
2d8f30380 [PATCH] sanitize ... |
474 |
set_fs_root(current->fs, &path); |
1da177e4c Linux-2.6.12-rc2 |
475 476 |
error = 0; dput_and_out: |
2d8f30380 [PATCH] sanitize ... |
477 |
path_put(&path); |
2771261ec vfs: have chroot ... |
478 479 480 481 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
1da177e4c Linux-2.6.12-rc2 |
482 483 484 |
out: return error; } |
be01f9f28 constify chmod_co... |
485 |
static int chmod_common(const struct path *path, umode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
486 |
{ |
e57712ebe merge fchmod() an... |
487 |
struct inode *inode = path->dentry->d_inode; |
27ac0ffea locks: break dele... |
488 |
struct inode *delegated_inode = NULL; |
1da177e4c Linux-2.6.12-rc2 |
489 |
struct iattr newattrs; |
e57712ebe merge fchmod() an... |
490 |
int error; |
1da177e4c Linux-2.6.12-rc2 |
491 |
|
e57712ebe merge fchmod() an... |
492 493 494 |
error = mnt_want_write(path->mnt); if (error) return error; |
27ac0ffea locks: break dele... |
495 |
retry_deleg: |
5955102c9 wrappers for ->i_... |
496 |
inode_lock(inode); |
cdcf116d4 switch security_p... |
497 |
error = security_path_chmod(path, mode); |
e57712ebe merge fchmod() an... |
498 |
if (error) |
fe542cf59 LSM: Move securit... |
499 |
goto out_unlock; |
1da177e4c Linux-2.6.12-rc2 |
500 501 |
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
27ac0ffea locks: break dele... |
502 |
error = notify_change(path->dentry, &newattrs, &delegated_inode); |
fe542cf59 LSM: Move securit... |
503 |
out_unlock: |
5955102c9 wrappers for ->i_... |
504 |
inode_unlock(inode); |
27ac0ffea locks: break dele... |
505 506 507 508 509 |
if (delegated_inode) { error = break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; } |
e57712ebe merge fchmod() an... |
510 511 512 |
mnt_drop_write(path->mnt); return error; } |
49f0a0767 switch sys_chmod(... |
513 |
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode) |
e57712ebe merge fchmod() an... |
514 |
{ |
173c84012 switch fchmod() t... |
515 |
struct fd f = fdget(fd); |
e57712ebe merge fchmod() an... |
516 |
int err = -EBADF; |
173c84012 switch fchmod() t... |
517 |
if (f.file) { |
9f45f5bf3 new helper: audit... |
518 |
audit_file(f.file); |
173c84012 switch fchmod() t... |
519 520 |
err = chmod_common(&f.file->f_path, mode); fdput(f); |
e57712ebe merge fchmod() an... |
521 |
} |
1da177e4c Linux-2.6.12-rc2 |
522 523 |
return err; } |
49f0a0767 switch sys_chmod(... |
524 |
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode) |
1da177e4c Linux-2.6.12-rc2 |
525 |
{ |
2d8f30380 [PATCH] sanitize ... |
526 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
527 |
int error; |
14ff690c0 vfs: make fchmoda... |
528 529 530 |
unsigned int lookup_flags = LOOKUP_FOLLOW; retry: error = user_path_at(dfd, filename, lookup_flags, &path); |
e57712ebe merge fchmod() an... |
531 532 533 |
if (!error) { error = chmod_common(&path, mode); path_put(&path); |
14ff690c0 vfs: make fchmoda... |
534 535 536 537 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
e57712ebe merge fchmod() an... |
538 |
} |
1da177e4c Linux-2.6.12-rc2 |
539 540 |
return error; } |
49f0a0767 switch sys_chmod(... |
541 |
SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode) |
5590ff0d5 [PATCH] vfs: *at ... |
542 543 544 |
{ return sys_fchmodat(AT_FDCWD, filename, mode); } |
7fd25dac9 constify chown_co... |
545 |
static int chown_common(const struct path *path, uid_t user, gid_t group) |
1da177e4c Linux-2.6.12-rc2 |
546 |
{ |
fe542cf59 LSM: Move securit... |
547 |
struct inode *inode = path->dentry->d_inode; |
27ac0ffea locks: break dele... |
548 |
struct inode *delegated_inode = NULL; |
1da177e4c Linux-2.6.12-rc2 |
549 550 |
int error; struct iattr newattrs; |
52137abe1 userns: Convert u... |
551 552 553 554 555 |
kuid_t uid; kgid_t gid; uid = make_kuid(current_user_ns(), user); gid = make_kgid(current_user_ns(), group); |
1da177e4c Linux-2.6.12-rc2 |
556 |
|
c1b8940b4 NFS: fix BUG() cr... |
557 |
retry_deleg: |
1da177e4c Linux-2.6.12-rc2 |
558 559 |
newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) -1) { |
52137abe1 userns: Convert u... |
560 561 |
if (!uid_valid(uid)) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
562 |
newattrs.ia_valid |= ATTR_UID; |
52137abe1 userns: Convert u... |
563 |
newattrs.ia_uid = uid; |
1da177e4c Linux-2.6.12-rc2 |
564 565 |
} if (group != (gid_t) -1) { |
52137abe1 userns: Convert u... |
566 567 |
if (!gid_valid(gid)) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
568 |
newattrs.ia_valid |= ATTR_GID; |
52137abe1 userns: Convert u... |
569 |
newattrs.ia_gid = gid; |
1da177e4c Linux-2.6.12-rc2 |
570 571 |
} if (!S_ISDIR(inode->i_mode)) |
b53767719 Implement file po... |
572 573 |
newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; |
5955102c9 wrappers for ->i_... |
574 |
inode_lock(inode); |
d2b31ca64 userns: Teach sec... |
575 |
error = security_path_chown(path, uid, gid); |
fe542cf59 LSM: Move securit... |
576 |
if (!error) |
27ac0ffea locks: break dele... |
577 |
error = notify_change(path->dentry, &newattrs, &delegated_inode); |
5955102c9 wrappers for ->i_... |
578 |
inode_unlock(inode); |
27ac0ffea locks: break dele... |
579 580 581 582 583 |
if (delegated_inode) { error = break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; } |
1da177e4c Linux-2.6.12-rc2 |
584 585 |
return error; } |
6559eed8c [CVE-2009-0029] S... |
586 587 |
SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag) |
5590ff0d5 [PATCH] vfs: *at ... |
588 |
{ |
2d8f30380 [PATCH] sanitize ... |
589 |
struct path path; |
5590ff0d5 [PATCH] vfs: *at ... |
590 |
int error = -EINVAL; |
65cfc6722 readlinkat(), fch... |
591 |
int lookup_flags; |
5590ff0d5 [PATCH] vfs: *at ... |
592 |
|
65cfc6722 readlinkat(), fch... |
593 |
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) |
5590ff0d5 [PATCH] vfs: *at ... |
594 |
goto out; |
65cfc6722 readlinkat(), fch... |
595 596 597 |
lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; if (flag & AT_EMPTY_PATH) lookup_flags |= LOOKUP_EMPTY; |
99a5df37a vfs: make fchowna... |
598 |
retry: |
65cfc6722 readlinkat(), fch... |
599 |
error = user_path_at(dfd, filename, lookup_flags, &path); |
6902d925d [PATCH] r/o bind ... |
600 601 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
602 |
error = mnt_want_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
603 604 |
if (error) goto out_release; |
fe542cf59 LSM: Move securit... |
605 |
error = chown_common(&path, user, group); |
2d8f30380 [PATCH] sanitize ... |
606 |
mnt_drop_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
607 |
out_release: |
2d8f30380 [PATCH] sanitize ... |
608 |
path_put(&path); |
99a5df37a vfs: make fchowna... |
609 610 611 612 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
5590ff0d5 [PATCH] vfs: *at ... |
613 614 615 |
out: return error; } |
55e4def0a VFS: Make chown()... |
616 |
SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) |
1da177e4c Linux-2.6.12-rc2 |
617 |
{ |
55e4def0a VFS: Make chown()... |
618 619 |
return sys_fchownat(AT_FDCWD, filename, user, group, 0); } |
1da177e4c Linux-2.6.12-rc2 |
620 |
|
55e4def0a VFS: Make chown()... |
621 622 623 624 |
SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group) { return sys_fchownat(AT_FDCWD, filename, user, group, AT_SYMLINK_NOFOLLOW); |
1da177e4c Linux-2.6.12-rc2 |
625 |
} |
ca013e945 [CVE-2009-0029] S... |
626 |
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) |
1da177e4c Linux-2.6.12-rc2 |
627 |
{ |
2903ff019 switch simple cas... |
628 |
struct fd f = fdget(fd); |
1da177e4c Linux-2.6.12-rc2 |
629 |
int error = -EBADF; |
2903ff019 switch simple cas... |
630 |
if (!f.file) |
6902d925d [PATCH] r/o bind ... |
631 |
goto out; |
7c6893e3c ovl: don't allow ... |
632 |
error = mnt_want_write_file_path(f.file); |
2af482a7e [PATCH] r/o bind ... |
633 634 |
if (error) goto out_fput; |
9f45f5bf3 new helper: audit... |
635 |
audit_file(f.file); |
2903ff019 switch simple cas... |
636 |
error = chown_common(&f.file->f_path, user, group); |
7c6893e3c ovl: don't allow ... |
637 |
mnt_drop_write_file_path(f.file); |
2af482a7e [PATCH] r/o bind ... |
638 |
out_fput: |
2903ff019 switch simple cas... |
639 |
fdput(f); |
6902d925d [PATCH] r/o bind ... |
640 |
out: |
1da177e4c Linux-2.6.12-rc2 |
641 642 |
return error; } |
90ad1a8ec vfs: split __dent... |
643 644 645 646 |
int open_check_o_direct(struct file *f) { /* NB: we're sure to have correct a_ops only after f_op->open */ if (f->f_flags & O_DIRECT) { |
e748dcd09 vfs: remove get_x... |
647 |
if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO) |
90ad1a8ec vfs: split __dent... |
648 |
return -EINVAL; |
90ad1a8ec vfs: split __dent... |
649 650 651 |
} return 0; } |
02e5180d9 do_dentry_open():... |
652 |
static int do_dentry_open(struct file *f, |
4bacc9c92 overlayfs: Make f... |
653 |
struct inode *inode, |
96b7e579a switch do_dentry_... |
654 655 |
int (*open)(struct inode *, struct file *), const struct cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
656 |
{ |
1abf0c718 New kind of open ... |
657 |
static const struct file_operations empty_fops = {}; |
1da177e4c Linux-2.6.12-rc2 |
658 |
int error; |
5300990c0 Sanitize f_flags ... |
659 |
f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | |
a1a5b3d93 [PATCH] open retu... |
660 |
FMODE_PREAD | FMODE_PWRITE; |
1abf0c718 New kind of open ... |
661 |
|
b5bcdda32 take grabbing f->... |
662 |
path_get(&f->f_path); |
4bacc9c92 overlayfs: Make f... |
663 |
f->f_inode = inode; |
1da177e4c Linux-2.6.12-rc2 |
664 |
f->f_mapping = inode->i_mapping; |
1da177e4c Linux-2.6.12-rc2 |
665 |
|
5660e13d2 fs: new infrastru... |
666 667 |
/* Ensure that we skip any errors that predate opening of the file */ f->f_wb_err = filemap_sample_wb_err(f->f_mapping); |
3f4d5a000 tidy do_dentry_op... |
668 669 |
if (unlikely(f->f_flags & O_PATH)) { f->f_mode = FMODE_PATH; |
1abf0c718 New kind of open ... |
670 |
f->f_op = &empty_fops; |
96b7e579a switch do_dentry_... |
671 |
return 0; |
1abf0c718 New kind of open ... |
672 |
} |
dd20908a8 don't bother with... |
673 |
if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) { |
0ccb28634 fold __get_file_w... |
674 |
error = get_write_access(inode); |
3f4d5a000 tidy do_dentry_op... |
675 |
if (unlikely(error)) |
1da177e4c Linux-2.6.12-rc2 |
676 |
goto cleanup_file; |
0ccb28634 fold __get_file_w... |
677 |
error = __mnt_want_write(f->f_path.mnt); |
3f4d5a000 tidy do_dentry_op... |
678 |
if (unlikely(error)) { |
0ccb28634 fold __get_file_w... |
679 680 681 |
put_write_access(inode); goto cleanup_file; } |
83f936c75 mark struct file ... |
682 |
f->f_mode |= FMODE_WRITER; |
1da177e4c Linux-2.6.12-rc2 |
683 |
} |
9c225f265 vfs: atomic f_pos... |
684 |
/* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */ |
63b6df141 give readdir(2)/g... |
685 |
if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) |
9c225f265 vfs: atomic f_pos... |
686 |
f->f_mode |= FMODE_ATOMIC_POS; |
1abf0c718 New kind of open ... |
687 |
f->f_op = fops_get(inode->i_fop); |
72c2d5319 file->f_op is nev... |
688 689 690 691 |
if (unlikely(WARN_ON(!f->f_op))) { error = -ENODEV; goto cleanup_all; } |
1abf0c718 New kind of open ... |
692 |
|
83d498569 SELinux: rename d... |
693 |
error = security_file_open(f, cred); |
788e7dd4c SELinux: Improve ... |
694 695 |
if (error) goto cleanup_all; |
c568d6834 locks: fix file l... |
696 |
error = break_lease(locks_inode(f), f->f_flags); |
f3c7691e8 leases: fix write... |
697 698 |
if (error) goto cleanup_all; |
72c2d5319 file->f_op is nev... |
699 |
if (!open) |
834f2a4a1 VFS: Allow the fi... |
700 701 702 |
open = f->f_op->open; if (open) { error = open(inode, f); |
1da177e4c Linux-2.6.12-rc2 |
703 704 705 |
if (error) goto cleanup_all; } |
890275b5e IMA: maintain i_r... |
706 707 |
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) i_readcount_inc(inode); |
293bc9822 new methods: ->re... |
708 |
if ((f->f_mode & FMODE_READ) && |
843631820 ->aio_read and ->... |
709 |
likely(f->f_op->read || f->f_op->read_iter)) |
7f7f25e82 replace checking ... |
710 |
f->f_mode |= FMODE_CAN_READ; |
293bc9822 new methods: ->re... |
711 |
if ((f->f_mode & FMODE_WRITE) && |
843631820 ->aio_read and ->... |
712 |
likely(f->f_op->write || f->f_op->write_iter)) |
7f7f25e82 replace checking ... |
713 |
f->f_mode |= FMODE_CAN_WRITE; |
834f2a4a1 VFS: Allow the fi... |
714 |
|
c75b1d942 fs: add fcntl() i... |
715 |
f->f_write_hint = WRITE_LIFE_NOT_SET; |
1da177e4c Linux-2.6.12-rc2 |
716 717 718 |
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); |
96b7e579a switch do_dentry_... |
719 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
720 721 722 |
cleanup_all: fops_put(f->f_op); |
83f936c75 mark struct file ... |
723 |
if (f->f_mode & FMODE_WRITER) { |
1da177e4c Linux-2.6.12-rc2 |
724 |
put_write_access(inode); |
83f936c75 mark struct file ... |
725 |
__mnt_drop_write(f->f_path.mnt); |
4a3fd211c [PATCH] r/o bind ... |
726 |
} |
1da177e4c Linux-2.6.12-rc2 |
727 |
cleanup_file: |
02e5180d9 do_dentry_open():... |
728 729 730 |
path_put(&f->f_path); f->f_path.mnt = NULL; f->f_path.dentry = NULL; |
dd37978c5 cache the value o... |
731 |
f->f_inode = NULL; |
96b7e579a switch do_dentry_... |
732 |
return error; |
1da177e4c Linux-2.6.12-rc2 |
733 |
} |
834f2a4a1 VFS: Allow the fi... |
734 |
/** |
d18e9008c vfs: add i_op->at... |
735 |
* finish_open - finish opening a file |
0854d450e vfs: improve i_op... |
736 |
* @file: file pointer |
d18e9008c vfs: add i_op->at... |
737 738 |
* @dentry: pointer to dentry * @open: open callback |
0854d450e vfs: improve i_op... |
739 |
* @opened: state of open |
d18e9008c vfs: add i_op->at... |
740 741 742 743 744 |
* * This can be used to finish opening a file passed to i_op->atomic_open(). * * If the open callback is set to NULL, then the standard f_op->open() * filesystem callback is substituted. |
0854d450e vfs: improve i_op... |
745 746 747 748 749 750 751 752 753 |
* * NB: the dentry reference is _not_ consumed. If, for example, the dentry is * the return value of d_splice_alias(), then the caller needs to perform dput() * on it after finish_open(). * * On successful return @file is a fully instantiated open file. After this, if * an error occurs in ->atomic_open(), it needs to clean up with fput(). * * Returns zero on success or -errno if the open failed. |
d18e9008c vfs: add i_op->at... |
754 |
*/ |
30d904947 kill struct opendata |
755 756 757 |
int finish_open(struct file *file, struct dentry *dentry, int (*open)(struct inode *, struct file *), int *opened) |
d18e9008c vfs: add i_op->at... |
758 |
{ |
96b7e579a switch do_dentry_... |
759 |
int error; |
3d8a00d20 don't modify od->... |
760 |
BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */ |
d18e9008c vfs: add i_op->at... |
761 |
|
b5bcdda32 take grabbing f->... |
762 |
file->f_path.dentry = dentry; |
4bacc9c92 overlayfs: Make f... |
763 764 |
error = do_dentry_open(file, d_backing_inode(dentry), open, current_cred()); |
96b7e579a switch do_dentry_... |
765 |
if (!error) |
47237687d ->atomic_open() p... |
766 |
*opened |= FILE_OPENED; |
d18e9008c vfs: add i_op->at... |
767 |
|
96b7e579a switch do_dentry_... |
768 |
return error; |
d18e9008c vfs: add i_op->at... |
769 770 771 772 773 774 |
} EXPORT_SYMBOL(finish_open); /** * finish_no_open - finish ->atomic_open() without opening the file * |
0854d450e vfs: improve i_op... |
775 |
* @file: file pointer |
d18e9008c vfs: add i_op->at... |
776 777 778 |
* @dentry: dentry or NULL (as returned from ->lookup()) * * This can be used to set the result of a successful lookup in ->atomic_open(). |
0854d450e vfs: improve i_op... |
779 780 781 782 783 784 |
* * NB: unlike finish_open() this function does consume the dentry reference and * the caller need not dput() it. * * Returns "1" which must be the return value of ->atomic_open() after having * called this function. |
d18e9008c vfs: add i_op->at... |
785 |
*/ |
e45198a6a make finish_no_op... |
786 |
int finish_no_open(struct file *file, struct dentry *dentry) |
d18e9008c vfs: add i_op->at... |
787 |
{ |
30d904947 kill struct opendata |
788 |
file->f_path.dentry = dentry; |
e45198a6a make finish_no_op... |
789 |
return 1; |
d18e9008c vfs: add i_op->at... |
790 791 |
} EXPORT_SYMBOL(finish_no_open); |
9bf39ab2a vfs: add file_pat... |
792 793 794 795 796 |
char *file_path(struct file *filp, char *buf, int buflen) { return d_path(&filp->f_path, buf, buflen); } EXPORT_SYMBOL(file_path); |
4bacc9c92 overlayfs: Make f... |
797 798 799 800 801 802 803 804 805 |
/** * vfs_open - open the file at the given path * @path: path to open * @file: newly allocated file with f_flag initialized * @cred: credentials to use */ int vfs_open(const struct path *path, struct file *file, const struct cred *cred) { |
495e64293 vfs: add flags to... |
806 |
struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags, 0); |
4bacc9c92 overlayfs: Make f... |
807 |
|
2d902671c vfs: merge .d_sel... |
808 809 |
if (IS_ERR(dentry)) return PTR_ERR(dentry); |
4bacc9c92 overlayfs: Make f... |
810 |
|
54d5ca871 vfs: add vfs_sele... |
811 |
file->f_path = *path; |
2d902671c vfs: merge .d_sel... |
812 |
return do_dentry_open(file, d_backing_inode(dentry), NULL, cred); |
4bacc9c92 overlayfs: Make f... |
813 |
} |
765927b2d switch dentry_ope... |
814 |
struct file *dentry_open(const struct path *path, int flags, |
745ca2475 CRED: Pass creden... |
815 |
const struct cred *cred) |
a1a5b3d93 [PATCH] open retu... |
816 817 818 |
{ int error; struct file *f; |
e0e817392 CRED: Add some co... |
819 |
validate_creds(cred); |
c212f9aaf fs: Use BUG_ON(!m... |
820 |
/* We must always pass in a valid mount pointer. */ |
765927b2d switch dentry_ope... |
821 |
BUG_ON(!path->mnt); |
322ee5b36 [PATCH] check for... |
822 |
|
a1a5b3d93 [PATCH] open retu... |
823 |
f = get_empty_filp(); |
1afc99bea propagate error f... |
824 825 |
if (!IS_ERR(f)) { f->f_flags = flags; |
4aa7c6346 vfs: add i_op->de... |
826 |
error = vfs_open(path, f, cred); |
1afc99bea propagate error f... |
827 828 829 830 831 832 833 834 835 |
if (!error) { /* from now on we need fput() to dispose of f */ error = open_check_o_direct(f); if (error) { fput(f); f = ERR_PTR(error); } } else { put_filp(f); |
2a027e7a1 fold __dentry_ope... |
836 837 |
f = ERR_PTR(error); } |
2a027e7a1 fold __dentry_ope... |
838 839 |
} return f; |
a1a5b3d93 [PATCH] open retu... |
840 |
} |
1da177e4c Linux-2.6.12-rc2 |
841 |
EXPORT_SYMBOL(dentry_open); |
a218d0fdc switch open and m... |
842 |
static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op) |
47c805dc2 switch do_filp_op... |
843 844 |
{ int lookup_flags = 0; |
62fb4a155 don't carry MAY_O... |
845 |
int acc_mode = ACC_MODE(flags); |
47c805dc2 switch do_filp_op... |
846 |
|
629e014bb fs: completely ig... |
847 848 849 850 851 |
/* * Clear out all open flags we don't know about so that we don't report * them in fcntl(F_GETFD) or similar interfaces. */ flags &= VALID_OPEN_FLAGS; |
e305f48bc fs: Fix file mode... |
852 |
if (flags & (O_CREAT | __O_TMPFILE)) |
e68726ff7 vfs: canonicalize... |
853 854 855 |
op->mode = (mode & S_IALLUGO) | S_IFREG; else op->mode = 0; |
47c805dc2 switch do_filp_op... |
856 857 |
/* Must never be set by userspace */ |
c6f3d8111 don't leak O_CLOE... |
858 |
flags &= ~FMODE_NONOTIFY & ~O_CLOEXEC; |
47c805dc2 switch do_filp_op... |
859 860 861 862 863 864 865 866 867 |
/* * 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; |
bb458c644 Safer ABI for O_T... |
868 869 |
if (flags & __O_TMPFILE) { if ((flags & O_TMPFILE_MASK) != O_TMPFILE) |
60545d0d4 [O_TMPFILE] it's ... |
870 |
return -EINVAL; |
ba57ea64c allow O_TMPFILE t... |
871 872 |
if (!(acc_mode & MAY_WRITE)) return -EINVAL; |
60545d0d4 [O_TMPFILE] it's ... |
873 874 875 876 877 |
} else if (flags & O_PATH) { /* * If we have O_PATH in the open flag. Then we * cannot have anything other than the below set of flags */ |
1abf0c718 New kind of open ... |
878 879 |
flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH; acc_mode = 0; |
1abf0c718 New kind of open ... |
880 |
} |
47c805dc2 switch do_filp_op... |
881 |
|
1abf0c718 New kind of open ... |
882 |
op->open_flag = flags; |
47c805dc2 switch do_filp_op... |
883 884 885 886 887 888 889 890 891 892 893 |
/* 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 New kind of open ... |
894 |
op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN; |
47c805dc2 switch do_filp_op... |
895 896 897 898 899 900 901 902 903 904 |
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; |
f9652e10c allow build_open_... |
905 906 |
op->lookup_flags = lookup_flags; return 0; |
47c805dc2 switch do_filp_op... |
907 908 909 |
} /** |
669abf4e5 vfs: make path_op... |
910 911 912 913 914 915 916 917 918 919 920 921 922 |
* file_open_name - open file and return file pointer * * @name: struct filename containing 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.. */ struct file *file_open_name(struct filename *name, int flags, umode_t mode) { struct open_flags op; |
f9652e10c allow build_open_... |
923 924 |
int err = build_open_flags(flags, mode, &op); return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op); |
669abf4e5 vfs: make path_op... |
925 926 927 |
} /** |
47c805dc2 switch do_filp_op... |
928 929 930 931 932 933 934 935 936 937 |
* 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 switch open and m... |
938 |
struct file *filp_open(const char *filename, int flags, umode_t mode) |
47c805dc2 switch do_filp_op... |
939 |
{ |
516891041 fs: create proper... |
940 941 942 943 944 945 946 947 |
struct filename *name = getname_kernel(filename); struct file *file = ERR_CAST(name); if (!IS_ERR(name)) { file = file_open_name(name, flags, mode); putname(name); } return file; |
47c805dc2 switch do_filp_op... |
948 949 |
} EXPORT_SYMBOL(filp_open); |
73d049a40 open-style analog... |
950 |
struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, |
378c6520e fs/coredump: prev... |
951 |
const char *filename, int flags, umode_t mode) |
73d049a40 open-style analog... |
952 953 |
{ struct open_flags op; |
378c6520e fs/coredump: prev... |
954 |
int err = build_open_flags(flags, mode, &op); |
f9652e10c allow build_open_... |
955 956 |
if (err) return ERR_PTR(err); |
f9652e10c allow build_open_... |
957 |
return do_file_open_root(dentry, mnt, filename, &op); |
73d049a40 open-style analog... |
958 959 |
} EXPORT_SYMBOL(file_open_root); |
9a08c352d fs: add filp_clon... |
960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
struct file *filp_clone_open(struct file *oldfile) { struct file *file; int retval; file = get_empty_filp(); if (IS_ERR(file)) return file; file->f_flags = oldfile->f_flags; retval = vfs_open(&oldfile->f_path, file, oldfile->f_cred); if (retval) { put_filp(file); return ERR_PTR(retval); } return file; } EXPORT_SYMBOL(filp_clone_open); |
a218d0fdc switch open and m... |
979 |
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
980 |
{ |
47c805dc2 switch do_filp_op... |
981 |
struct open_flags op; |
f9652e10c allow build_open_... |
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 |
int fd = build_open_flags(flags, mode, &op); struct filename *tmp; if (fd) return fd; tmp = getname(filename); if (IS_ERR(tmp)) return PTR_ERR(tmp); fd = get_unused_fd_flags(flags); if (fd >= 0) { struct file *f = do_filp_open(dfd, tmp, &op); if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); } else { fsnotify_open(f); fd_install(fd, f); |
1da177e4c Linux-2.6.12-rc2 |
1001 |
} |
1da177e4c Linux-2.6.12-rc2 |
1002 |
} |
f9652e10c allow build_open_... |
1003 |
putname(tmp); |
1da177e4c Linux-2.6.12-rc2 |
1004 |
return fd; |
1da177e4c Linux-2.6.12-rc2 |
1005 |
} |
e922efc34 [PATCH] remove du... |
1006 |
|
a218d0fdc switch open and m... |
1007 |
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) |
e922efc34 [PATCH] remove du... |
1008 1009 1010 |
{ if (force_o_largefile()) flags |= O_LARGEFILE; |
2cf096668 make SYSCALL_DEFI... |
1011 |
return do_sys_open(AT_FDCWD, filename, flags, mode); |
e922efc34 [PATCH] remove du... |
1012 |
} |
1da177e4c Linux-2.6.12-rc2 |
1013 |
|
6559eed8c [CVE-2009-0029] S... |
1014 |
SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, |
a218d0fdc switch open and m... |
1015 |
umode_t, mode) |
5590ff0d5 [PATCH] vfs: *at ... |
1016 1017 1018 |
{ if (force_o_largefile()) flags |= O_LARGEFILE; |
2cf096668 make SYSCALL_DEFI... |
1019 |
return do_sys_open(dfd, filename, flags, mode); |
5590ff0d5 [PATCH] vfs: *at ... |
1020 |
} |
5590ff0d5 [PATCH] vfs: *at ... |
1021 |
|
e35d49f63 open: move compat... |
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
#ifdef CONFIG_COMPAT /* * Exactly like sys_open(), except that it doesn't set the * O_LARGEFILE flag. */ COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) { return do_sys_open(AT_FDCWD, filename, flags, mode); } /* * Exactly like sys_openat(), except that it doesn't set the * O_LARGEFILE flag. */ COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode) { return do_sys_open(dfd, filename, flags, mode); } #endif |
1da177e4c Linux-2.6.12-rc2 |
1041 1042 1043 1044 1045 1046 |
#ifndef __alpha__ /* * For backward compatibility? Maybe this should be moved * into arch/i386 instead? */ |
a218d0fdc switch open and m... |
1047 |
SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode) |
1da177e4c Linux-2.6.12-rc2 |
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 |
{ 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 [PATCH] Remove f_... |
1060 |
int retval = 0; |
1da177e4c Linux-2.6.12-rc2 |
1061 1062 1063 1064 |
if (!file_count(filp)) { printk(KERN_ERR "VFS: Close: file count is 0 "); |
45778ca81 [PATCH] Remove f_... |
1065 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1066 |
} |
72c2d5319 file->f_op is nev... |
1067 |
if (filp->f_op->flush) |
75e1fcc0b [PATCH] vfs: add ... |
1068 |
retval = filp->f_op->flush(filp, id); |
1da177e4c Linux-2.6.12-rc2 |
1069 |
|
1abf0c718 New kind of open ... |
1070 1071 1072 1073 |
if (likely(!(filp->f_mode & FMODE_PATH))) { dnotify_flush(filp, id); locks_remove_posix(filp, id); } |
1da177e4c Linux-2.6.12-rc2 |
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 |
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 [CVE-2009-0029] S... |
1085 |
SYSCALL_DEFINE1(close, unsigned int, fd) |
1da177e4c Linux-2.6.12-rc2 |
1086 |
{ |
483ce1d4b take descriptor-r... |
1087 |
int retval = __close_fd(current->files, fd); |
ee731f4f7 [PATCH] fix wrong... |
1088 1089 1090 1091 1092 1093 1094 1095 1096 |
/* 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 Linux-2.6.12-rc2 |
1097 |
} |
1da177e4c Linux-2.6.12-rc2 |
1098 1099 1100 1101 1102 1103 |
EXPORT_SYMBOL(sys_close); /* * This routine simulates a hangup on the tty, to arrange that users * are given clean terminals at login time. */ |
ca013e945 [CVE-2009-0029] S... |
1104 |
SYSCALL_DEFINE0(vhangup) |
1da177e4c Linux-2.6.12-rc2 |
1105 1106 |
{ if (capable(CAP_SYS_TTY_CONFIG)) { |
2cb5998b5 tty: the vhangup ... |
1107 |
tty_vhangup_self(); |
1da177e4c Linux-2.6.12-rc2 |
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
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 fs: correct SuS c... |
1122 |
return -EOVERFLOW; |
1da177e4c Linux-2.6.12-rc2 |
1123 1124 1125 1126 1127 1128 1129 |
return 0; } EXPORT_SYMBOL(generic_file_open); /* * This is used by subsystems that don't want seekable |
06b1e104b vfs: clarify that... |
1130 1131 1132 |
* 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 Linux-2.6.12-rc2 |
1133 1134 1135 1136 1137 1138 1139 1140 |
*/ int nonseekable_open(struct inode *inode, struct file *filp) { filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); return 0; } EXPORT_SYMBOL(nonseekable_open); |