Blame view
fs/open.c
23.6 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> |
1da177e4c Linux-2.6.12-rc2 |
22 23 |
#include <asm/uaccess.h> #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> |
1da177e4c Linux-2.6.12-rc2 |
32 |
|
e81e3f4dc fs: move get_empt... |
33 |
#include "internal.h" |
4a30131e7 [PATCH] Fix some ... |
34 35 |
int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, struct file *filp) |
1da177e4c Linux-2.6.12-rc2 |
36 |
{ |
939a9421e vfs: allow file t... |
37 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 41 42 43 44 |
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 ... |
45 |
newattrs.ia_valid = ATTR_SIZE | time_attrs; |
cc4e69dee [PATCH] VFS: pass... |
46 47 48 49 |
if (filp) { newattrs.ia_file = filp; newattrs.ia_valid |= ATTR_FILE; } |
1da177e4c Linux-2.6.12-rc2 |
50 |
|
7b82dc0e6 Remove suid/sgid ... |
51 |
/* Remove suid/sgid on truncate too */ |
939a9421e vfs: allow file t... |
52 53 54 |
ret = should_remove_suid(dentry); if (ret) newattrs.ia_valid |= ret | ATTR_FORCE; |
7b82dc0e6 Remove suid/sgid ... |
55 |
|
1b1dcc1b5 [PATCH] mutex sub... |
56 |
mutex_lock(&dentry->d_inode->i_mutex); |
939a9421e vfs: allow file t... |
57 |
ret = notify_change(dentry, &newattrs); |
1b1dcc1b5 [PATCH] mutex sub... |
58 |
mutex_unlock(&dentry->d_inode->i_mutex); |
939a9421e vfs: allow file t... |
59 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
60 |
} |
2d8f30380 [PATCH] sanitize ... |
61 |
static long do_sys_truncate(const char __user *pathname, loff_t length) |
1da177e4c Linux-2.6.12-rc2 |
62 |
{ |
2d8f30380 [PATCH] sanitize ... |
63 64 |
struct path path; struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
65 66 67 68 69 |
int error; error = -EINVAL; if (length < 0) /* sorry, but loff_t says... */ goto out; |
2d8f30380 [PATCH] sanitize ... |
70 |
error = user_path(pathname, &path); |
1da177e4c Linux-2.6.12-rc2 |
71 72 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
73 |
inode = path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
74 75 76 77 78 79 80 81 82 |
/* 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 [PATCH] sanitize ... |
83 |
error = mnt_want_write(path.mnt); |
1da177e4c Linux-2.6.12-rc2 |
84 85 |
if (error) goto dput_and_out; |
256984a83 [PATCH] preparati... |
86 |
error = inode_permission(inode, MAY_WRITE); |
9ac9b8474 [PATCH] r/o bind ... |
87 88 |
if (error) goto mnt_drop_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
89 90 |
error = -EPERM; |
c82e42da8 [patch 1/5] vfs: ... |
91 |
if (IS_APPEND(inode)) |
9ac9b8474 [PATCH] r/o bind ... |
92 |
goto mnt_drop_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
93 |
|
9700382c3 VFS: fix a race i... |
94 |
error = get_write_access(inode); |
1da177e4c Linux-2.6.12-rc2 |
95 |
if (error) |
9ac9b8474 [PATCH] r/o bind ... |
96 |
goto mnt_drop_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
97 |
|
9700382c3 VFS: fix a race i... |
98 99 100 101 |
/* * Make sure that there are no leases. get_write_access() protects * against the truncate racing with a lease-granting setlease(). */ |
8737c9305 Switch may_open()... |
102 |
error = break_lease(inode, O_WRONLY); |
1da177e4c Linux-2.6.12-rc2 |
103 |
if (error) |
9700382c3 VFS: fix a race i... |
104 |
goto put_write_and_out; |
1da177e4c Linux-2.6.12-rc2 |
105 106 |
error = locks_verify_truncate(inode, NULL, length); |
be6d3e56a introduce new LSM... |
107 108 |
if (!error) error = security_path_truncate(&path, length, 0); |
907f4554e dquot: move dquot... |
109 |
if (!error) |
2d8f30380 [PATCH] sanitize ... |
110 |
error = do_truncate(path.dentry, length, 0, NULL); |
1da177e4c Linux-2.6.12-rc2 |
111 |
|
9700382c3 VFS: fix a race i... |
112 113 |
put_write_and_out: put_write_access(inode); |
9ac9b8474 [PATCH] r/o bind ... |
114 |
mnt_drop_write_and_out: |
2d8f30380 [PATCH] sanitize ... |
115 |
mnt_drop_write(path.mnt); |
1da177e4c Linux-2.6.12-rc2 |
116 |
dput_and_out: |
2d8f30380 [PATCH] sanitize ... |
117 |
path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
118 119 120 |
out: return error; } |
4fd8da8d6 fs: change sys_tr... |
121 |
SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) |
1da177e4c Linux-2.6.12-rc2 |
122 |
{ |
4fd8da8d6 fs: change sys_tr... |
123 |
return do_sys_truncate(path, length); |
1da177e4c Linux-2.6.12-rc2 |
124 |
} |
b01ec0ef6 [PATCH] tiny: Uni... |
125 |
static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) |
1da177e4c Linux-2.6.12-rc2 |
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
{ 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 [PATCH] VFS: chan... |
143 |
dentry = file->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
inode = dentry->d_inode; error = -EINVAL; if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) goto out_putf; error = -EINVAL; /* Cannot ftruncate over 2^31 bytes without large file support */ if (small && length > MAX_NON_LFS) goto out_putf; error = -EPERM; if (IS_APPEND(inode)) goto out_putf; error = locks_verify_truncate(inode, file, length); if (!error) |
be6d3e56a introduce new LSM... |
160 161 162 |
error = security_path_truncate(&file->f_path, length, ATTR_MTIME|ATTR_CTIME); if (!error) |
6e656be89 [PATCH] ftruncate... |
163 |
error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); |
1da177e4c Linux-2.6.12-rc2 |
164 165 166 167 168 |
out_putf: fput(file); out: return error; } |
bdc480e3b [CVE-2009-0029] S... |
169 |
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length) |
1da177e4c Linux-2.6.12-rc2 |
170 |
{ |
0a489cb3b x86: don't allow ... |
171 |
long ret = do_sys_ftruncate(fd, length, 1); |
385910f2b x86: be careful a... |
172 |
/* avoid REGPARM breakage on x86: */ |
54a015104 asmlinkage_protec... |
173 |
asmlinkage_protect(2, ret, fd, length); |
0a489cb3b x86: don't allow ... |
174 |
return ret; |
1da177e4c 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 [CVE-2009-0029] S... |
179 |
SYSCALL_DEFINE(truncate64)(const char __user * path, loff_t length) |
1da177e4c Linux-2.6.12-rc2 |
180 181 182 |
{ return do_sys_truncate(path, length); } |
6673e0c3f [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 Linux-2.6.12-rc2 |
190 |
|
6673e0c3f [CVE-2009-0029] S... |
191 |
SYSCALL_DEFINE(ftruncate64)(unsigned int fd, loff_t length) |
1da177e4c Linux-2.6.12-rc2 |
192 |
{ |
0a489cb3b x86: don't allow ... |
193 |
long ret = do_sys_ftruncate(fd, length, 0); |
385910f2b x86: be careful a... |
194 |
/* avoid REGPARM breakage on x86: */ |
54a015104 asmlinkage_protec... |
195 |
asmlinkage_protect(2, ret, fd, length); |
0a489cb3b x86: don't allow ... |
196 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
197 |
} |
6673e0c3f [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 Linux-2.6.12-rc2 |
204 |
#endif |
6673e0c3f [CVE-2009-0029] S... |
205 |
#endif /* BITS_PER_LONG == 32 */ |
1da177e4c Linux-2.6.12-rc2 |
206 |
|
3e63cbb1e fs: Add new pre-a... |
207 208 |
int do_fallocate(struct file *file, int mode, loff_t offset, loff_t len) |
97ac73506 sys_fallocate() i... |
209 |
{ |
3e63cbb1e fs: Add new pre-a... |
210 211 |
struct inode *inode = file->f_path.dentry->d_inode; long ret; |
97ac73506 sys_fallocate() i... |
212 213 |
if (offset < 0 || len <= 0) |
3e63cbb1e fs: Add new pre-a... |
214 |
return -EINVAL; |
97ac73506 sys_fallocate() i... |
215 216 |
/* Return error if mode is not supported */ |
97ac73506 sys_fallocate() i... |
217 |
if (mode && !(mode & FALLOC_FL_KEEP_SIZE)) |
3e63cbb1e fs: Add new pre-a... |
218 |
return -EOPNOTSUPP; |
97ac73506 sys_fallocate() i... |
219 |
|
97ac73506 sys_fallocate() i... |
220 |
if (!(file->f_mode & FMODE_WRITE)) |
3e63cbb1e fs: Add new pre-a... |
221 |
return -EBADF; |
97ac73506 sys_fallocate() i... |
222 223 224 225 226 227 |
/* * 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... |
228 |
return ret; |
97ac73506 sys_fallocate() i... |
229 |
|
97ac73506 sys_fallocate() i... |
230 |
if (S_ISFIFO(inode->i_mode)) |
3e63cbb1e fs: Add new pre-a... |
231 |
return -ESPIPE; |
97ac73506 sys_fallocate() i... |
232 |
|
97ac73506 sys_fallocate() i... |
233 234 235 236 237 |
/* * 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 fs: Add new pre-a... |
238 |
return -ENODEV; |
97ac73506 sys_fallocate() i... |
239 |
|
97ac73506 sys_fallocate() i... |
240 241 |
/* Check for wrap through zero too */ if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) |
3e63cbb1e fs: Add new pre-a... |
242 |
return -EFBIG; |
97ac73506 sys_fallocate() i... |
243 |
|
3e63cbb1e fs: Add new pre-a... |
244 245 |
if (!inode->i_op->fallocate) return -EOPNOTSUPP; |
97ac73506 sys_fallocate() i... |
246 |
|
3e63cbb1e fs: Add new pre-a... |
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
return inode->i_op->fallocate(inode, mode, offset, len); } 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 sys_fallocate() i... |
262 |
} |
3e63cbb1e fs: Add new pre-a... |
263 |
|
6673e0c3f [CVE-2009-0029] S... |
264 265 266 267 268 269 270 |
#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 sys_fallocate() i... |
271 |
|
1da177e4c Linux-2.6.12-rc2 |
272 273 274 275 276 |
/* * 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... |
277 |
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) |
1da177e4c Linux-2.6.12-rc2 |
278 |
{ |
d84f4f992 CRED: Inaugurate ... |
279 280 |
const struct cred *old_cred; struct cred *override_cred; |
2d8f30380 [PATCH] sanitize ... |
281 |
struct path path; |
256984a83 [PATCH] preparati... |
282 |
struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
283 284 285 286 |
int res; if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; |
d84f4f992 CRED: Inaugurate ... |
287 288 289 |
override_cred = prepare_creds(); if (!override_cred) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
290 |
|
d84f4f992 CRED: Inaugurate ... |
291 292 |
override_cred->fsuid = override_cred->uid; override_cred->fsgid = override_cred->gid; |
1da177e4c Linux-2.6.12-rc2 |
293 |
|
086f7316f security: filesys... |
294 |
if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
1cdcbec1a CRED: Neuter sys_... |
295 |
/* Clear the capabilities if we switch to a non-root user */ |
d84f4f992 CRED: Inaugurate ... |
296 297 |
if (override_cred->uid) cap_clear(override_cred->cap_effective); |
086f7316f security: filesys... |
298 |
else |
d84f4f992 CRED: Inaugurate ... |
299 300 |
override_cred->cap_effective = override_cred->cap_permitted; |
086f7316f security: filesys... |
301 |
} |
1da177e4c Linux-2.6.12-rc2 |
302 |
|
d84f4f992 CRED: Inaugurate ... |
303 |
old_cred = override_creds(override_cred); |
2d8f30380 [PATCH] sanitize ... |
304 |
res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
6902d925d [PATCH] r/o bind ... |
305 306 |
if (res) goto out; |
2d8f30380 [PATCH] sanitize ... |
307 |
inode = path.dentry->d_inode; |
256984a83 [PATCH] preparati... |
308 309 |
if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { |
30524472c [PATCH] take noex... |
310 311 312 313 314 |
/* * MAY_EXEC on regular files is denied if the fs is mounted * with the "noexec" flag. */ res = -EACCES; |
2d8f30380 [PATCH] sanitize ... |
315 |
if (path.mnt->mnt_flags & MNT_NOEXEC) |
30524472c [PATCH] take noex... |
316 317 |
goto out_path_release; } |
256984a83 [PATCH] preparati... |
318 |
res = inode_permission(inode, mode | MAY_ACCESS); |
6902d925d [PATCH] r/o bind ... |
319 |
/* SuS v2 requires we report a read only fs too */ |
256984a83 [PATCH] preparati... |
320 |
if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) |
6902d925d [PATCH] r/o bind ... |
321 |
goto out_path_release; |
2f676cbc0 [PATCH] r/o bind ... |
322 323 324 325 326 327 328 329 330 331 |
/* * 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 ... |
332 |
if (__mnt_is_readonly(path.mnt)) |
6902d925d [PATCH] r/o bind ... |
333 |
res = -EROFS; |
1da177e4c Linux-2.6.12-rc2 |
334 |
|
6902d925d [PATCH] r/o bind ... |
335 |
out_path_release: |
2d8f30380 [PATCH] sanitize ... |
336 |
path_put(&path); |
6902d925d [PATCH] r/o bind ... |
337 |
out: |
d84f4f992 CRED: Inaugurate ... |
338 339 |
revert_creds(old_cred); put_cred(override_cred); |
1da177e4c Linux-2.6.12-rc2 |
340 341 |
return res; } |
ca013e945 [CVE-2009-0029] S... |
342 |
SYSCALL_DEFINE2(access, const char __user *, filename, int, mode) |
5590ff0d5 [PATCH] vfs: *at ... |
343 344 345 |
{ return sys_faccessat(AT_FDCWD, filename, mode); } |
3cdad4288 [CVE-2009-0029] S... |
346 |
SYSCALL_DEFINE1(chdir, const char __user *, filename) |
1da177e4c Linux-2.6.12-rc2 |
347 |
{ |
2d8f30380 [PATCH] sanitize ... |
348 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
349 |
int error; |
2d8f30380 [PATCH] sanitize ... |
350 |
error = user_path_dir(filename, &path); |
1da177e4c Linux-2.6.12-rc2 |
351 352 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
353 |
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
1da177e4c Linux-2.6.12-rc2 |
354 355 |
if (error) goto dput_and_out; |
2d8f30380 [PATCH] sanitize ... |
356 |
set_fs_pwd(current->fs, &path); |
1da177e4c Linux-2.6.12-rc2 |
357 358 |
dput_and_out: |
2d8f30380 [PATCH] sanitize ... |
359 |
path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
360 361 362 |
out: return error; } |
3cdad4288 [CVE-2009-0029] S... |
363 |
SYSCALL_DEFINE1(fchdir, unsigned int, fd) |
1da177e4c Linux-2.6.12-rc2 |
364 365 |
{ struct file *file; |
1da177e4c Linux-2.6.12-rc2 |
366 |
struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
367 368 369 370 371 372 |
int error; error = -EBADF; file = fget(fd); if (!file) goto out; |
ac748a09f Make set_fs_{root... |
373 |
inode = file->f_path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
374 375 376 377 |
error = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) goto out_putf; |
256984a83 [PATCH] preparati... |
378 |
error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); |
1da177e4c Linux-2.6.12-rc2 |
379 |
if (!error) |
ac748a09f Make set_fs_{root... |
380 |
set_fs_pwd(current->fs, &file->f_path); |
1da177e4c Linux-2.6.12-rc2 |
381 382 383 384 385 |
out_putf: fput(file); out: return error; } |
3480b2574 [CVE-2009-0029] S... |
386 |
SYSCALL_DEFINE1(chroot, const char __user *, filename) |
1da177e4c Linux-2.6.12-rc2 |
387 |
{ |
2d8f30380 [PATCH] sanitize ... |
388 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
389 |
int error; |
2d8f30380 [PATCH] sanitize ... |
390 |
error = user_path_dir(filename, &path); |
1da177e4c Linux-2.6.12-rc2 |
391 392 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
393 |
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
1da177e4c Linux-2.6.12-rc2 |
394 395 396 397 398 399 |
if (error) goto dput_and_out; error = -EPERM; if (!capable(CAP_SYS_CHROOT)) goto dput_and_out; |
8b8efb440 LSM: Add security... |
400 401 402 |
error = security_path_chroot(&path); if (error) goto dput_and_out; |
1da177e4c Linux-2.6.12-rc2 |
403 |
|
2d8f30380 [PATCH] sanitize ... |
404 |
set_fs_root(current->fs, &path); |
1da177e4c Linux-2.6.12-rc2 |
405 406 |
error = 0; dput_and_out: |
2d8f30380 [PATCH] sanitize ... |
407 |
path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
408 409 410 |
out: return error; } |
a26eab240 [CVE-2009-0029] S... |
411 |
SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) |
1da177e4c Linux-2.6.12-rc2 |
412 413 414 415 416 417 418 419 420 421 |
{ struct inode * inode; struct dentry * dentry; struct file * file; int err = -EBADF; struct iattr newattrs; file = fget(fd); if (!file) goto out; |
0f7fc9e4d [PATCH] VFS: chan... |
422 |
dentry = file->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
423 |
inode = dentry->d_inode; |
5a190ae69 [PATCH] pass dent... |
424 |
audit_inode(NULL, dentry); |
73241ccca [PATCH] Collect m... |
425 |
|
96029c4e0 fs: introduce mnt... |
426 |
err = mnt_want_write_file(file); |
2af482a7e [PATCH] r/o bind ... |
427 |
if (err) |
1da177e4c Linux-2.6.12-rc2 |
428 |
goto out_putf; |
fe542cf59 LSM: Move securit... |
429 |
mutex_lock(&inode->i_mutex); |
89eda0683 LSM: Add security... |
430 431 |
err = security_path_chmod(dentry, file->f_vfsmnt, mode); if (err) |
fe542cf59 LSM: Move securit... |
432 |
goto out_unlock; |
1da177e4c Linux-2.6.12-rc2 |
433 434 435 436 437 |
if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); |
fe542cf59 LSM: Move securit... |
438 |
out_unlock: |
1b1dcc1b5 [PATCH] mutex sub... |
439 |
mutex_unlock(&inode->i_mutex); |
2af482a7e [PATCH] r/o bind ... |
440 |
mnt_drop_write(file->f_path.mnt); |
1da177e4c Linux-2.6.12-rc2 |
441 442 443 444 445 |
out_putf: fput(file); out: return err; } |
6559eed8c [CVE-2009-0029] S... |
446 |
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode) |
1da177e4c Linux-2.6.12-rc2 |
447 |
{ |
2d8f30380 [PATCH] sanitize ... |
448 449 |
struct path path; struct inode *inode; |
1da177e4c Linux-2.6.12-rc2 |
450 451 |
int error; struct iattr newattrs; |
2d8f30380 [PATCH] sanitize ... |
452 |
error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
1da177e4c Linux-2.6.12-rc2 |
453 454 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
455 |
inode = path.dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
456 |
|
2d8f30380 [PATCH] sanitize ... |
457 |
error = mnt_want_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
458 |
if (error) |
1da177e4c Linux-2.6.12-rc2 |
459 |
goto dput_and_out; |
fe542cf59 LSM: Move securit... |
460 |
mutex_lock(&inode->i_mutex); |
89eda0683 LSM: Add security... |
461 462 |
error = security_path_chmod(path.dentry, path.mnt, mode); if (error) |
fe542cf59 LSM: Move securit... |
463 |
goto out_unlock; |
1da177e4c Linux-2.6.12-rc2 |
464 465 466 467 |
if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
2d8f30380 [PATCH] sanitize ... |
468 |
error = notify_change(path.dentry, &newattrs); |
fe542cf59 LSM: Move securit... |
469 |
out_unlock: |
1b1dcc1b5 [PATCH] mutex sub... |
470 |
mutex_unlock(&inode->i_mutex); |
2d8f30380 [PATCH] sanitize ... |
471 |
mnt_drop_write(path.mnt); |
1da177e4c Linux-2.6.12-rc2 |
472 |
dput_and_out: |
2d8f30380 [PATCH] sanitize ... |
473 |
path_put(&path); |
1da177e4c Linux-2.6.12-rc2 |
474 475 476 |
out: return error; } |
a26eab240 [CVE-2009-0029] S... |
477 |
SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode) |
5590ff0d5 [PATCH] vfs: *at ... |
478 479 480 |
{ return sys_fchmodat(AT_FDCWD, filename, mode); } |
fe542cf59 LSM: Move securit... |
481 |
static int chown_common(struct path *path, uid_t user, gid_t group) |
1da177e4c Linux-2.6.12-rc2 |
482 |
{ |
fe542cf59 LSM: Move securit... |
483 |
struct inode *inode = path->dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
484 485 |
int error; struct iattr newattrs; |
1da177e4c Linux-2.6.12-rc2 |
486 487 488 489 490 491 492 493 494 495 |
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 Implement file po... |
496 497 |
newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; |
1b1dcc1b5 [PATCH] mutex sub... |
498 |
mutex_lock(&inode->i_mutex); |
fe542cf59 LSM: Move securit... |
499 500 501 |
error = security_path_chown(path, user, group); if (!error) error = notify_change(path->dentry, &newattrs); |
1b1dcc1b5 [PATCH] mutex sub... |
502 |
mutex_unlock(&inode->i_mutex); |
beb29e058 [patch 4/4] vfs: ... |
503 |
|
1da177e4c Linux-2.6.12-rc2 |
504 505 |
return error; } |
ca013e945 [CVE-2009-0029] S... |
506 |
SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) |
1da177e4c Linux-2.6.12-rc2 |
507 |
{ |
2d8f30380 [PATCH] sanitize ... |
508 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
509 |
int error; |
2d8f30380 [PATCH] sanitize ... |
510 |
error = user_path(filename, &path); |
6902d925d [PATCH] r/o bind ... |
511 512 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
513 |
error = mnt_want_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
514 515 |
if (error) goto out_release; |
fe542cf59 LSM: Move securit... |
516 |
error = chown_common(&path, user, group); |
2d8f30380 [PATCH] sanitize ... |
517 |
mnt_drop_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
518 |
out_release: |
2d8f30380 [PATCH] sanitize ... |
519 |
path_put(&path); |
6902d925d [PATCH] r/o bind ... |
520 |
out: |
1da177e4c Linux-2.6.12-rc2 |
521 522 |
return error; } |
6559eed8c [CVE-2009-0029] S... |
523 524 |
SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag) |
5590ff0d5 [PATCH] vfs: *at ... |
525 |
{ |
2d8f30380 [PATCH] sanitize ... |
526 |
struct path path; |
5590ff0d5 [PATCH] vfs: *at ... |
527 528 529 530 531 532 533 |
int error = -EINVAL; int follow; if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) goto out; follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; |
2d8f30380 [PATCH] sanitize ... |
534 |
error = user_path_at(dfd, filename, follow, &path); |
6902d925d [PATCH] r/o bind ... |
535 536 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
537 |
error = mnt_want_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
538 539 |
if (error) goto out_release; |
fe542cf59 LSM: Move securit... |
540 |
error = chown_common(&path, user, group); |
2d8f30380 [PATCH] sanitize ... |
541 |
mnt_drop_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
542 |
out_release: |
2d8f30380 [PATCH] sanitize ... |
543 |
path_put(&path); |
5590ff0d5 [PATCH] vfs: *at ... |
544 545 546 |
out: return error; } |
ca013e945 [CVE-2009-0029] S... |
547 |
SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group) |
1da177e4c Linux-2.6.12-rc2 |
548 |
{ |
2d8f30380 [PATCH] sanitize ... |
549 |
struct path path; |
1da177e4c Linux-2.6.12-rc2 |
550 |
int error; |
2d8f30380 [PATCH] sanitize ... |
551 |
error = user_lpath(filename, &path); |
6902d925d [PATCH] r/o bind ... |
552 553 |
if (error) goto out; |
2d8f30380 [PATCH] sanitize ... |
554 |
error = mnt_want_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
555 556 |
if (error) goto out_release; |
fe542cf59 LSM: Move securit... |
557 |
error = chown_common(&path, user, group); |
2d8f30380 [PATCH] sanitize ... |
558 |
mnt_drop_write(path.mnt); |
2af482a7e [PATCH] r/o bind ... |
559 |
out_release: |
2d8f30380 [PATCH] sanitize ... |
560 |
path_put(&path); |
6902d925d [PATCH] r/o bind ... |
561 |
out: |
1da177e4c Linux-2.6.12-rc2 |
562 563 |
return error; } |
ca013e945 [CVE-2009-0029] S... |
564 |
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) |
1da177e4c Linux-2.6.12-rc2 |
565 566 567 |
{ struct file * file; int error = -EBADF; |
6902d925d [PATCH] r/o bind ... |
568 |
struct dentry * dentry; |
1da177e4c Linux-2.6.12-rc2 |
569 570 |
file = fget(fd); |
6902d925d [PATCH] r/o bind ... |
571 572 |
if (!file) goto out; |
96029c4e0 fs: introduce mnt... |
573 |
error = mnt_want_write_file(file); |
2af482a7e [PATCH] r/o bind ... |
574 575 |
if (error) goto out_fput; |
0f7fc9e4d [PATCH] VFS: chan... |
576 |
dentry = file->f_path.dentry; |
5a190ae69 [PATCH] pass dent... |
577 |
audit_inode(NULL, dentry); |
fe542cf59 LSM: Move securit... |
578 |
error = chown_common(&file->f_path, user, group); |
2af482a7e [PATCH] r/o bind ... |
579 580 |
mnt_drop_write(file->f_path.mnt); out_fput: |
6902d925d [PATCH] r/o bind ... |
581 582 |
fput(file); out: |
1da177e4c Linux-2.6.12-rc2 |
583 584 |
return error; } |
4a3fd211c [PATCH] r/o bind ... |
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
/* * 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 [PATCH] open retu... |
613 |
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, |
482928d59 Fix f_flags/f_mod... |
614 |
struct file *f, |
745ca2475 CRED: Pass creden... |
615 616 |
int (*open)(struct inode *, struct file *), const struct cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
617 |
{ |
1da177e4c Linux-2.6.12-rc2 |
618 619 |
struct inode *inode; int error; |
5300990c0 Sanitize f_flags ... |
620 |
f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK | |
a1a5b3d93 [PATCH] open retu... |
621 |
FMODE_PREAD | FMODE_PWRITE; |
1da177e4c Linux-2.6.12-rc2 |
622 623 |
inode = dentry->d_inode; if (f->f_mode & FMODE_WRITE) { |
4a3fd211c [PATCH] r/o bind ... |
624 |
error = __get_file_write_access(inode, mnt); |
1da177e4c Linux-2.6.12-rc2 |
625 626 |
if (error) goto cleanup_file; |
ad775f5a8 [PATCH] r/o bind ... |
627 628 |
if (!special_file(inode->i_mode)) file_take_write(f); |
1da177e4c Linux-2.6.12-rc2 |
629 630 631 |
} f->f_mapping = inode->i_mapping; |
0f7fc9e4d [PATCH] VFS: chan... |
632 633 |
f->f_path.dentry = dentry; f->f_path.mnt = mnt; |
1da177e4c Linux-2.6.12-rc2 |
634 635 636 |
f->f_pos = 0; f->f_op = fops_get(inode->i_fop); file_move(f, &inode->i_sb->s_files); |
745ca2475 CRED: Pass creden... |
637 |
error = security_dentry_open(f, cred); |
788e7dd4c SELinux: Improve ... |
638 639 |
if (error) goto cleanup_all; |
834f2a4a1 VFS: Allow the fi... |
640 641 642 643 |
if (!open && f->f_op) open = f->f_op->open; if (open) { error = open(inode, f); |
1da177e4c Linux-2.6.12-rc2 |
644 645 646 |
if (error) goto cleanup_all; } |
b65a9cfc2 Untangling ima me... |
647 |
ima_counts_get(f); |
834f2a4a1 VFS: Allow the fi... |
648 |
|
1da177e4c Linux-2.6.12-rc2 |
649 650 651 652 653 654 |
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 [PATCH] xip: fs/m... |
655 656 |
if (!f->f_mapping->a_ops || ((!f->f_mapping->a_ops->direct_IO) && |
70688e4dd xip: support non-... |
657 |
(!f->f_mapping->a_ops->get_xip_mem))) { |
1da177e4c Linux-2.6.12-rc2 |
658 659 660 661 662 663 664 665 666 |
fput(f); f = ERR_PTR(-EINVAL); } } return f; cleanup_all: fops_put(f->f_op); |
4a3fd211c [PATCH] r/o bind ... |
667 |
if (f->f_mode & FMODE_WRITE) { |
1da177e4c Linux-2.6.12-rc2 |
668 |
put_write_access(inode); |
ad775f5a8 [PATCH] r/o bind ... |
669 670 671 672 673 674 675 676 |
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 [PATCH] r/o bind ... |
677 |
mnt_drop_write(mnt); |
ad775f5a8 [PATCH] r/o bind ... |
678 |
} |
4a3fd211c [PATCH] r/o bind ... |
679 |
} |
1da177e4c Linux-2.6.12-rc2 |
680 |
file_kill(f); |
0f7fc9e4d [PATCH] VFS: chan... |
681 682 |
f->f_path.dentry = NULL; f->f_path.mnt = NULL; |
1da177e4c Linux-2.6.12-rc2 |
683 684 |
cleanup_file: put_filp(f); |
1da177e4c Linux-2.6.12-rc2 |
685 686 687 688 |
dput(dentry); mntput(mnt); return ERR_PTR(error); } |
834f2a4a1 VFS: Allow the fi... |
689 690 691 692 693 694 695 696 697 698 |
/** * 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 [PATCH] Add looku... |
699 700 701 702 |
* 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 VFS: Allow the fi... |
703 704 705 706 707 708 709 710 |
* 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 CRED: Pass creden... |
711 |
const struct cred *cred = current_cred(); |
834f2a4a1 VFS: Allow the fi... |
712 713 714 715 |
if (IS_ERR(nd->intent.open.file)) goto out; if (IS_ERR(dentry)) goto out_err; |
4ac913785 Embed a struct pa... |
716 |
nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), |
834f2a4a1 VFS: Allow the fi... |
717 |
nd->intent.open.file, |
745ca2475 CRED: Pass creden... |
718 |
open, cred); |
834f2a4a1 VFS: Allow the fi... |
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 |
out: return nd->intent.open.file; out_err: release_open_intent(nd); nd->intent.open.file = (struct file *)dentry; goto out; } EXPORT_SYMBOL_GPL(lookup_instantiate_filp); /** * nameidata_to_filp - convert a nameidata to an open filp. * @nd: pointer to nameidata * @flags: open flags * * Note that this function destroys the original nameidata */ |
482928d59 Fix f_flags/f_mod... |
735 |
struct file *nameidata_to_filp(struct nameidata *nd) |
834f2a4a1 VFS: Allow the fi... |
736 |
{ |
745ca2475 CRED: Pass creden... |
737 |
const struct cred *cred = current_cred(); |
834f2a4a1 VFS: Allow the fi... |
738 739 740 741 742 |
struct file *filp; /* Pick up the filp from the open intent */ filp = nd->intent.open.file; /* Has the filesystem initialised the file for us? */ |
0f7fc9e4d [PATCH] VFS: chan... |
743 |
if (filp->f_path.dentry == NULL) |
482928d59 Fix f_flags/f_mod... |
744 |
filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, |
745ca2475 CRED: Pass creden... |
745 |
NULL, cred); |
834f2a4a1 VFS: Allow the fi... |
746 |
else |
1d957f9bf Introduce path_put() |
747 |
path_put(&nd->path); |
834f2a4a1 VFS: Allow the fi... |
748 749 |
return filp; } |
6fdcc2162 [PATCH] memory le... |
750 751 752 753 |
/* * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an * error. */ |
745ca2475 CRED: Pass creden... |
754 755 |
struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, const struct cred *cred) |
a1a5b3d93 [PATCH] open retu... |
756 757 758 |
{ int error; struct file *f; |
e0e817392 CRED: Add some co... |
759 |
validate_creds(cred); |
322ee5b36 [PATCH] check for... |
760 761 762 763 764 765 766 767 768 769 770 771 |
/* * We must always pass in a valid mount pointer. Historically * callers got away with not passing it, but we must enforce this at * the earliest possible point now to avoid strange problems deep in the * filesystem stack. */ if (!mnt) { printk(KERN_WARNING "%s called with NULL vfsmount ", __func__); dump_stack(); return ERR_PTR(-EINVAL); } |
a1a5b3d93 [PATCH] open retu... |
772 773 |
error = -ENFILE; f = get_empty_filp(); |
6fdcc2162 [PATCH] memory le... |
774 775 776 |
if (f == NULL) { dput(dentry); mntput(mnt); |
a1a5b3d93 [PATCH] open retu... |
777 |
return ERR_PTR(error); |
6fdcc2162 [PATCH] memory le... |
778 |
} |
a1a5b3d93 [PATCH] open retu... |
779 |
|
482928d59 Fix f_flags/f_mod... |
780 781 |
f->f_flags = flags; return __dentry_open(dentry, mnt, f, NULL, cred); |
a1a5b3d93 [PATCH] open retu... |
782 |
} |
1da177e4c Linux-2.6.12-rc2 |
783 |
EXPORT_SYMBOL(dentry_open); |
b01ec0ef6 [PATCH] tiny: Uni... |
784 |
static void __put_unused_fd(struct files_struct *files, unsigned int fd) |
1da177e4c Linux-2.6.12-rc2 |
785 |
{ |
badf16621 [PATCH] files: br... |
786 787 |
struct fdtable *fdt = files_fdtable(files); __FD_CLR(fd, fdt->open_fds); |
0c9e63fd3 [PATCH] Shrinks s... |
788 789 |
if (fd < files->next_fd) files->next_fd = fd; |
1da177e4c Linux-2.6.12-rc2 |
790 |
} |
fc9b52cd8 fs: remove fastca... |
791 |
void put_unused_fd(unsigned int fd) |
1da177e4c Linux-2.6.12-rc2 |
792 793 794 795 796 797 798 799 800 801 |
{ 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 [PATCH] vfs: *at ... |
802 |
* Install a file pointer in the fd array. |
1da177e4c Linux-2.6.12-rc2 |
803 804 805 806 807 808 809 810 811 812 |
* * 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 fs: remove fastca... |
813 |
void fd_install(unsigned int fd, struct file *file) |
1da177e4c Linux-2.6.12-rc2 |
814 815 |
{ struct files_struct *files = current->files; |
badf16621 [PATCH] files: br... |
816 |
struct fdtable *fdt; |
1da177e4c Linux-2.6.12-rc2 |
817 |
spin_lock(&files->file_lock); |
badf16621 [PATCH] files: br... |
818 |
fdt = files_fdtable(files); |
ab2af1f50 [PATCH] files: fi... |
819 820 |
BUG_ON(fdt->fd[fd] != NULL); rcu_assign_pointer(fdt->fd[fd], file); |
1da177e4c Linux-2.6.12-rc2 |
821 822 823 824 |
spin_unlock(&files->file_lock); } EXPORT_SYMBOL(fd_install); |
5590ff0d5 [PATCH] vfs: *at ... |
825 |
long do_sys_open(int dfd, const char __user *filename, int flags, int mode) |
1da177e4c Linux-2.6.12-rc2 |
826 |
{ |
e922efc34 [PATCH] remove du... |
827 828 |
char *tmp = getname(filename); int fd = PTR_ERR(tmp); |
1da177e4c Linux-2.6.12-rc2 |
829 |
|
1da177e4c Linux-2.6.12-rc2 |
830 |
if (!IS_ERR(tmp)) { |
f23513e8d Introduce O_CLOEXEC |
831 |
fd = get_unused_fd_flags(flags); |
1da177e4c Linux-2.6.12-rc2 |
832 |
if (fd >= 0) { |
6e8341a11 Switch open_exec(... |
833 |
struct file *f = do_filp_open(dfd, tmp, flags, mode, 0); |
fed2fc18a [PATCH] sys_open(... |
834 835 836 837 |
if (IS_ERR(f)) { put_unused_fd(fd); fd = PTR_ERR(f); } else { |
0f7fc9e4d [PATCH] VFS: chan... |
838 |
fsnotify_open(f->f_path.dentry); |
fed2fc18a [PATCH] sys_open(... |
839 840 |
fd_install(fd, f); } |
1da177e4c Linux-2.6.12-rc2 |
841 |
} |
1da177e4c Linux-2.6.12-rc2 |
842 843 844 |
putname(tmp); } return fd; |
1da177e4c Linux-2.6.12-rc2 |
845 |
} |
e922efc34 [PATCH] remove du... |
846 |
|
ca013e945 [CVE-2009-0029] S... |
847 |
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode) |
e922efc34 [PATCH] remove du... |
848 |
{ |
385910f2b x86: be careful a... |
849 |
long ret; |
e922efc34 [PATCH] remove du... |
850 851 |
if (force_o_largefile()) flags |= O_LARGEFILE; |
385910f2b x86: be careful a... |
852 853 |
ret = do_sys_open(AT_FDCWD, filename, flags, mode); /* avoid REGPARM breakage on x86: */ |
54a015104 asmlinkage_protec... |
854 |
asmlinkage_protect(3, ret, filename, flags, mode); |
385910f2b x86: be careful a... |
855 |
return ret; |
e922efc34 [PATCH] remove du... |
856 |
} |
1da177e4c Linux-2.6.12-rc2 |
857 |
|
6559eed8c [CVE-2009-0029] S... |
858 859 |
SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, int, mode) |
5590ff0d5 [PATCH] vfs: *at ... |
860 |
{ |
385910f2b x86: be careful a... |
861 |
long ret; |
5590ff0d5 [PATCH] vfs: *at ... |
862 863 |
if (force_o_largefile()) flags |= O_LARGEFILE; |
385910f2b x86: be careful a... |
864 865 |
ret = do_sys_open(dfd, filename, flags, mode); /* avoid REGPARM breakage on x86: */ |
54a015104 asmlinkage_protec... |
866 |
asmlinkage_protect(4, ret, dfd, filename, flags, mode); |
385910f2b x86: be careful a... |
867 |
return ret; |
5590ff0d5 [PATCH] vfs: *at ... |
868 |
} |
5590ff0d5 [PATCH] vfs: *at ... |
869 |
|
1da177e4c Linux-2.6.12-rc2 |
870 871 872 873 874 875 |
#ifndef __alpha__ /* * For backward compatibility? Maybe this should be moved * into arch/i386 instead? */ |
002c8976e [CVE-2009-0029] S... |
876 |
SYSCALL_DEFINE2(creat, const char __user *, pathname, int, mode) |
1da177e4c Linux-2.6.12-rc2 |
877 878 879 880 881 882 883 884 885 886 887 888 |
{ 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_... |
889 |
int retval = 0; |
1da177e4c Linux-2.6.12-rc2 |
890 891 892 893 |
if (!file_count(filp)) { printk(KERN_ERR "VFS: Close: file count is 0 "); |
45778ca81 [PATCH] Remove f_... |
894 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
895 |
} |
45778ca81 [PATCH] Remove f_... |
896 |
if (filp->f_op && filp->f_op->flush) |
75e1fcc0b [PATCH] vfs: add ... |
897 |
retval = filp->f_op->flush(filp, id); |
1da177e4c Linux-2.6.12-rc2 |
898 899 900 901 902 903 904 905 906 907 908 909 910 911 |
dnotify_flush(filp, id); locks_remove_posix(filp, id); fput(filp); return retval; } EXPORT_SYMBOL(filp_close); /* * Careful here! We test whether the file pointer is NULL before * releasing the fd. This ensures that one clone task can't release * an fd while another clone is opening it. */ |
ca013e945 [CVE-2009-0029] S... |
912 |
SYSCALL_DEFINE1(close, unsigned int, fd) |
1da177e4c Linux-2.6.12-rc2 |
913 914 915 |
{ struct file * filp; struct files_struct *files = current->files; |
badf16621 [PATCH] files: br... |
916 |
struct fdtable *fdt; |
ee731f4f7 [PATCH] fix wrong... |
917 |
int retval; |
1da177e4c Linux-2.6.12-rc2 |
918 919 |
spin_lock(&files->file_lock); |
badf16621 [PATCH] files: br... |
920 921 |
fdt = files_fdtable(files); if (fd >= fdt->max_fds) |
1da177e4c Linux-2.6.12-rc2 |
922 |
goto out_unlock; |
badf16621 [PATCH] files: br... |
923 |
filp = fdt->fd[fd]; |
1da177e4c Linux-2.6.12-rc2 |
924 925 |
if (!filp) goto out_unlock; |
ab2af1f50 [PATCH] files: fi... |
926 |
rcu_assign_pointer(fdt->fd[fd], NULL); |
badf16621 [PATCH] files: br... |
927 |
FD_CLR(fd, fdt->close_on_exec); |
1da177e4c Linux-2.6.12-rc2 |
928 929 |
__put_unused_fd(files, fd); spin_unlock(&files->file_lock); |
ee731f4f7 [PATCH] fix wrong... |
930 931 932 933 934 935 936 937 938 939 |
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 Linux-2.6.12-rc2 |
940 941 942 943 944 |
out_unlock: spin_unlock(&files->file_lock); return -EBADF; } |
1da177e4c Linux-2.6.12-rc2 |
945 946 947 948 949 950 |
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... |
951 |
SYSCALL_DEFINE0(vhangup) |
1da177e4c Linux-2.6.12-rc2 |
952 953 |
{ if (capable(CAP_SYS_TTY_CONFIG)) { |
2cb5998b5 tty: the vhangup ... |
954 |
tty_vhangup_self(); |
1da177e4c Linux-2.6.12-rc2 |
955 956 957 958 959 960 961 962 963 964 965 966 967 968 |
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... |
969 |
return -EOVERFLOW; |
1da177e4c Linux-2.6.12-rc2 |
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 |
return 0; } EXPORT_SYMBOL(generic_file_open); /* * This is used by subsystems that don't want seekable * file descriptors */ int nonseekable_open(struct inode *inode, struct file *filp) { filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); return 0; } EXPORT_SYMBOL(nonseekable_open); |