Blame view
fs/open.c
34.7 KB
457c89965
|
1 |
// SPDX-License-Identifier: GPL-2.0-only |
1da177e4c
|
2 3 4 5 6 7 8 9 |
/* * linux/fs/open.c * * Copyright (C) 1991, 1992 Linus Torvalds */ #include <linux/string.h> #include <linux/mm.h> |
1da177e4c
|
10 |
#include <linux/file.h> |
9f3acc314
|
11 |
#include <linux/fdtable.h> |
0eeca2830
|
12 |
#include <linux/fsnotify.h> |
1da177e4c
|
13 |
#include <linux/module.h> |
1da177e4c
|
14 15 16 |
#include <linux/tty.h> #include <linux/namei.h> #include <linux/backing-dev.h> |
16f7e0fe2
|
17 |
#include <linux/capability.h> |
086f7316f
|
18 |
#include <linux/securebits.h> |
1da177e4c
|
19 20 |
#include <linux/security.h> #include <linux/mount.h> |
5590ff0d5
|
21 |
#include <linux/fcntl.h> |
5a0e3ad6a
|
22 |
#include <linux/slab.h> |
7c0f6ba68
|
23 |
#include <linux/uaccess.h> |
1da177e4c
|
24 |
#include <linux/fs.h> |
ef3daeda7
|
25 |
#include <linux/personality.h> |
1da177e4c
|
26 27 |
#include <linux/pagemap.h> #include <linux/syscalls.h> |
ab2af1f50
|
28 |
#include <linux/rcupdate.h> |
73241ccca
|
29 |
#include <linux/audit.h> |
97ac73506
|
30 |
#include <linux/falloc.h> |
5ad4e53bd
|
31 |
#include <linux/fs_struct.h> |
b65a9cfc2
|
32 |
#include <linux/ima.h> |
2dfc1cae4
|
33 |
#include <linux/dnotify.h> |
3f6d078d4
|
34 |
#include <linux/compat.h> |
7bc23abcb
|
35 |
#include <linux/mnt_idmapping.h> |
1da177e4c
|
36 |
|
e81e3f4dc
|
37 |
#include "internal.h" |
643fe55a0
|
38 39 |
int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry, loff_t length, unsigned int time_attrs, struct file *filp) |
1da177e4c
|
40 |
{ |
939a9421e
|
41 |
int ret; |
1da177e4c
|
42 43 44 45 46 47 48 |
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
|
49 |
newattrs.ia_valid = ATTR_SIZE | time_attrs; |
cc4e69dee
|
50 51 52 53 |
if (filp) { newattrs.ia_file = filp; newattrs.ia_valid |= ATTR_FILE; } |
1da177e4c
|
54 |
|
45f147a1b
|
55 56 57 58 |
/* Remove suid, sgid, and file capabilities on truncate too */ ret = dentry_needs_remove_privs(dentry); if (ret < 0) return ret; |
939a9421e
|
59 60 |
if (ret) newattrs.ia_valid |= ret | ATTR_FORCE; |
7b82dc0e6
|
61 |
|
5955102c9
|
62 |
inode_lock(dentry->d_inode); |
27ac0ffea
|
63 |
/* Note any delegations or leases have already been broken: */ |
643fe55a0
|
64 |
ret = notify_change(mnt_userns, dentry, &newattrs, NULL); |
5955102c9
|
65 |
inode_unlock(dentry->d_inode); |
939a9421e
|
66 |
return ret; |
1da177e4c
|
67 |
} |
7df818b23
|
68 |
long vfs_truncate(const struct path *path, loff_t length) |
1da177e4c
|
69 |
{ |
643fe55a0
|
70 |
struct user_namespace *mnt_userns; |
2d8f30380
|
71 |
struct inode *inode; |
a02de9608
|
72 |
long error; |
1da177e4c
|
73 |
|
a02de9608
|
74 |
inode = path->dentry->d_inode; |
1da177e4c
|
75 76 |
/* For directories it's -EISDIR, for other non-regulars - -EINVAL */ |
1da177e4c
|
77 |
if (S_ISDIR(inode->i_mode)) |
a02de9608
|
78 |
return -EISDIR; |
1da177e4c
|
79 |
if (!S_ISREG(inode->i_mode)) |
a02de9608
|
80 |
return -EINVAL; |
1da177e4c
|
81 |
|
a02de9608
|
82 |
error = mnt_want_write(path->mnt); |
1da177e4c
|
83 |
if (error) |
a02de9608
|
84 |
goto out; |
1da177e4c
|
85 |
|
643fe55a0
|
86 87 |
mnt_userns = mnt_user_ns(path->mnt); error = inode_permission(mnt_userns, inode, MAY_WRITE); |
9ac9b8474
|
88 89 |
if (error) goto mnt_drop_write_and_out; |
1da177e4c
|
90 91 |
error = -EPERM; |
c82e42da8
|
92 |
if (IS_APPEND(inode)) |
9ac9b8474
|
93 |
goto mnt_drop_write_and_out; |
1da177e4c
|
94 |
|
8cf9ee506
|
95 |
error = get_write_access(inode); |
1da177e4c
|
96 |
if (error) |
9ac9b8474
|
97 |
goto mnt_drop_write_and_out; |
1da177e4c
|
98 |
|
9700382c3
|
99 100 101 102 |
/* * Make sure that there are no leases. get_write_access() protects * against the truncate racing with a lease-granting setlease(). */ |
8737c9305
|
103 |
error = break_lease(inode, O_WRONLY); |
1da177e4c
|
104 |
if (error) |
9700382c3
|
105 |
goto put_write_and_out; |
1da177e4c
|
106 |
|
f7e33bdbd
|
107 |
error = security_path_truncate(path); |
907f4554e
|
108 |
if (!error) |
643fe55a0
|
109 |
error = do_truncate(mnt_userns, path->dentry, length, 0, NULL); |
1da177e4c
|
110 |
|
9700382c3
|
111 |
put_write_and_out: |
8cf9ee506
|
112 |
put_write_access(inode); |
9ac9b8474
|
113 |
mnt_drop_write_and_out: |
a02de9608
|
114 |
mnt_drop_write(path->mnt); |
1da177e4c
|
115 116 117 |
out: return error; } |
a02de9608
|
118 |
EXPORT_SYMBOL_GPL(vfs_truncate); |
df260e21e
|
119 |
long do_sys_truncate(const char __user *pathname, loff_t length) |
a02de9608
|
120 |
{ |
48f7530d3
|
121 |
unsigned int lookup_flags = LOOKUP_FOLLOW; |
a02de9608
|
122 123 124 125 126 |
struct path path; int error; if (length < 0) /* sorry, but loff_t says... */ return -EINVAL; |
48f7530d3
|
127 128 |
retry: error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); |
a02de9608
|
129 130 131 132 |
if (!error) { error = vfs_truncate(&path, length); path_put(&path); } |
48f7530d3
|
133 134 135 136 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
a02de9608
|
137 138 |
return error; } |
1da177e4c
|
139 |
|
4fd8da8d6
|
140 |
SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) |
1da177e4c
|
141 |
{ |
4fd8da8d6
|
142 |
return do_sys_truncate(path, length); |
1da177e4c
|
143 |
} |
3f6d078d4
|
144 145 146 147 148 149 |
#ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(truncate, const char __user *, path, compat_off_t, length) { return do_sys_truncate(path, length); } #endif |
411d9475c
|
150 |
long do_sys_ftruncate(unsigned int fd, loff_t length, int small) |
1da177e4c
|
151 |
{ |
bf2965d5b
|
152 |
struct inode *inode; |
1da177e4c
|
153 |
struct dentry *dentry; |
2903ff019
|
154 |
struct fd f; |
1da177e4c
|
155 156 157 158 159 160 |
int error; error = -EINVAL; if (length < 0) goto out; error = -EBADF; |
2903ff019
|
161 162 |
f = fdget(fd); if (!f.file) |
1da177e4c
|
163 164 165 |
goto out; /* explicitly opened as large or we are on 64-bit box */ |
2903ff019
|
166 |
if (f.file->f_flags & O_LARGEFILE) |
1da177e4c
|
167 |
small = 0; |
2903ff019
|
168 |
dentry = f.file->f_path.dentry; |
1da177e4c
|
169 170 |
inode = dentry->d_inode; error = -EINVAL; |
2903ff019
|
171 |
if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE)) |
1da177e4c
|
172 173 174 175 176 177 178 179 |
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
|
180 181 |
/* Check IS_APPEND on real upper inode */ if (IS_APPEND(file_inode(f.file))) |
1da177e4c
|
182 |
goto out_putf; |
14da92001
|
183 |
sb_start_write(inode->i_sb); |
f7e33bdbd
|
184 |
error = security_path_truncate(&f.file->f_path); |
be6d3e56a
|
185 |
if (!error) |
643fe55a0
|
186 187 |
error = do_truncate(file_mnt_user_ns(f.file), dentry, length, ATTR_MTIME | ATTR_CTIME, f.file); |
14da92001
|
188 |
sb_end_write(inode->i_sb); |
1da177e4c
|
189 |
out_putf: |
2903ff019
|
190 |
fdput(f); |
1da177e4c
|
191 192 193 |
out: return error; } |
bdc480e3b
|
194 |
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length) |
1da177e4c
|
195 |
{ |
2cf096668
|
196 |
return do_sys_ftruncate(fd, length, 1); |
1da177e4c
|
197 |
} |
3f6d078d4
|
198 199 200 201 202 203 |
#ifdef CONFIG_COMPAT COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_ulong_t, length) { return do_sys_ftruncate(fd, length, 1); } #endif |
1da177e4c
|
204 205 |
/* LFS versions of truncate are only needed on 32 bit machines */ #if BITS_PER_LONG == 32 |
4a0fd5bf0
|
206 |
SYSCALL_DEFINE2(truncate64, const char __user *, path, loff_t, length) |
1da177e4c
|
207 208 209 |
{ return do_sys_truncate(path, length); } |
4a0fd5bf0
|
210 |
SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length) |
1da177e4c
|
211 |
{ |
2cf096668
|
212 |
return do_sys_ftruncate(fd, length, 0); |
1da177e4c
|
213 |
} |
6673e0c3f
|
214 |
#endif /* BITS_PER_LONG == 32 */ |
1da177e4c
|
215 |
|
3e63cbb1e
|
216 |
|
72c72bdf7
|
217 |
int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) |
97ac73506
|
218 |
{ |
496ad9aa8
|
219 |
struct inode *inode = file_inode(file); |
3e63cbb1e
|
220 |
long ret; |
97ac73506
|
221 222 |
if (offset < 0 || len <= 0) |
3e63cbb1e
|
223 |
return -EINVAL; |
97ac73506
|
224 225 |
/* Return error if mode is not supported */ |
dd46c7877
|
226 |
if (mode & ~FALLOC_FL_SUPPORTED_MASK) |
409332b65
|
227 228 229 230 231 |
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
|
232 233 234 235 236 |
return -EOPNOTSUPP; /* Punch hole must have keep size set */ if ((mode & FALLOC_FL_PUNCH_HOLE) && !(mode & FALLOC_FL_KEEP_SIZE)) |
3e63cbb1e
|
237 |
return -EOPNOTSUPP; |
97ac73506
|
238 |
|
00f5e6199
|
239 240 241 242 |
/* Collapse range should only be used exclusively. */ if ((mode & FALLOC_FL_COLLAPSE_RANGE) && (mode & ~FALLOC_FL_COLLAPSE_RANGE)) return -EINVAL; |
dd46c7877
|
243 244 245 246 |
/* Insert range should only be used exclusively. */ if ((mode & FALLOC_FL_INSERT_RANGE) && (mode & ~FALLOC_FL_INSERT_RANGE)) return -EINVAL; |
71be6b494
|
247 248 249 250 |
/* 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
|
251 |
if (!(file->f_mode & FMODE_WRITE)) |
3e63cbb1e
|
252 |
return -EBADF; |
1ca551c6c
|
253 |
|
00f5e6199
|
254 |
/* |
8fc61d926
|
255 |
* We can only allow pure fallocate on append only files |
00f5e6199
|
256 |
*/ |
8fc61d926
|
257 |
if ((mode & ~FALLOC_FL_KEEP_SIZE) && IS_APPEND(inode)) |
1ca551c6c
|
258 259 260 261 |
return -EPERM; if (IS_IMMUTABLE(inode)) return -EPERM; |
97ac73506
|
262 |
/* |
6d2b6170c
|
263 |
* We cannot allow any fallocate operation on an active swapfile |
0790b31b6
|
264 265 |
*/ if (IS_SWAPFILE(inode)) |
6d2b6170c
|
266 |
return -ETXTBSY; |
0790b31b6
|
267 268 |
/* |
97ac73506
|
269 270 271 272 273 |
* 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
|
274 |
return ret; |
97ac73506
|
275 |
|
97ac73506
|
276 |
if (S_ISFIFO(inode->i_mode)) |
3e63cbb1e
|
277 |
return -ESPIPE; |
97ac73506
|
278 |
|
9e79b1326
|
279 280 281 282 |
if (S_ISDIR(inode->i_mode)) return -EISDIR; if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) |
3e63cbb1e
|
283 |
return -ENODEV; |
97ac73506
|
284 |
|
97ac73506
|
285 286 |
/* Check for wrap through zero too */ if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) |
3e63cbb1e
|
287 |
return -EFBIG; |
97ac73506
|
288 |
|
2fe17c107
|
289 |
if (!file->f_op->fallocate) |
3e63cbb1e
|
290 |
return -EOPNOTSUPP; |
97ac73506
|
291 |
|
bfe219d37
|
292 |
file_start_write(file); |
14da92001
|
293 |
ret = file->f_op->fallocate(file, mode, offset, len); |
820c12d5d
|
294 295 296 297 298 299 300 301 302 303 |
/* * 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
|
304 |
file_end_write(file); |
14da92001
|
305 |
return ret; |
3e63cbb1e
|
306 |
} |
72c72bdf7
|
307 |
EXPORT_SYMBOL_GPL(vfs_fallocate); |
3e63cbb1e
|
308 |
|
edf292c76
|
309 |
int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len) |
3e63cbb1e
|
310 |
{ |
2903ff019
|
311 |
struct fd f = fdget(fd); |
3e63cbb1e
|
312 |
int error = -EBADF; |
2903ff019
|
313 |
if (f.file) { |
72c72bdf7
|
314 |
error = vfs_fallocate(f.file, mode, offset, len); |
2903ff019
|
315 |
fdput(f); |
3e63cbb1e
|
316 |
} |
3e63cbb1e
|
317 |
return error; |
97ac73506
|
318 |
} |
3e63cbb1e
|
319 |
|
edf292c76
|
320 321 322 323 |
SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len) { return ksys_fallocate(fd, mode, offset, len); } |
1da177e4c
|
324 325 326 327 328 |
/* * 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. */ |
947045150
|
329 |
static const struct cred *access_override_creds(void) |
1da177e4c
|
330 |
{ |
d84f4f992
|
331 332 |
const struct cred *old_cred; struct cred *override_cred; |
1da177e4c
|
333 |
|
d84f4f992
|
334 335 |
override_cred = prepare_creds(); if (!override_cred) |
947045150
|
336 |
return NULL; |
1da177e4c
|
337 |
|
d84f4f992
|
338 339 |
override_cred->fsuid = override_cred->uid; override_cred->fsgid = override_cred->gid; |
1da177e4c
|
340 |
|
086f7316f
|
341 |
if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
1cdcbec1a
|
342 |
/* Clear the capabilities if we switch to a non-root user */ |
18815a180
|
343 344 |
kuid_t root_uid = make_kuid(override_cred->user_ns, 0); if (!uid_eq(override_cred->uid, root_uid)) |
d84f4f992
|
345 |
cap_clear(override_cred->cap_effective); |
086f7316f
|
346 |
else |
d84f4f992
|
347 348 |
override_cred->cap_effective = override_cred->cap_permitted; |
086f7316f
|
349 |
} |
1da177e4c
|
350 |
|
d7852fbd0
|
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
/* * The new set of credentials can *only* be used in * task-synchronous circumstances, and does not need * RCU freeing, unless somebody then takes a separate * reference to it. * * NOTE! This is _only_ true because this credential * is used purely for override_creds() that installs * it as the subjective cred. Other threads will be * accessing ->real_cred, not the subjective cred. * * If somebody _does_ make a copy of this (using the * 'get_current_cred()' function), that will clear the * non_rcu field, because now that other user may be * expecting RCU freeing. But normal thread-synchronous * cred accesses will keep things non-RCY. */ override_cred->non_rcu = 1; |
d84f4f992
|
369 |
old_cred = override_creds(override_cred); |
947045150
|
370 371 372 373 374 375 |
/* override_cred() gets its own ref */ put_cred(override_cred); return old_cred; } |
eb9d7d390
|
376 |
static long do_faccessat(int dfd, const char __user *filename, int mode, int flags) |
947045150
|
377 378 379 380 381 |
{ struct path path; struct inode *inode; int res; unsigned int lookup_flags = LOOKUP_FOLLOW; |
c8ffd8bcd
|
382 |
const struct cred *old_cred = NULL; |
947045150
|
383 384 385 |
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ return -EINVAL; |
c8ffd8bcd
|
386 387 388 389 390 391 392 393 394 395 396 397 398 |
if (flags & ~(AT_EACCESS | AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) return -EINVAL; if (flags & AT_SYMLINK_NOFOLLOW) lookup_flags &= ~LOOKUP_FOLLOW; if (flags & AT_EMPTY_PATH) lookup_flags |= LOOKUP_EMPTY; if (!(flags & AT_EACCESS)) { old_cred = access_override_creds(); if (!old_cred) return -ENOMEM; } |
947045150
|
399 |
|
87fa55952
|
400 401 |
retry: res = user_path_at(dfd, filename, lookup_flags, &path); |
6902d925d
|
402 403 |
if (res) goto out; |
63afdfc78
|
404 |
inode = d_backing_inode(path.dentry); |
256984a83
|
405 406 |
if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { |
30524472c
|
407 408 409 410 411 |
/* * MAY_EXEC on regular files is denied if the fs is mounted * with the "noexec" flag. */ res = -EACCES; |
90f8572b0
|
412 |
if (path_noexec(&path)) |
30524472c
|
413 414 |
goto out_path_release; } |
b8b546a06
|
415 |
res = inode_permission(mnt_user_ns(path.mnt), inode, mode | MAY_ACCESS); |
6902d925d
|
416 |
/* SuS v2 requires we report a read only fs too */ |
256984a83
|
417 |
if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) |
6902d925d
|
418 |
goto out_path_release; |
2f676cbc0
|
419 420 421 422 423 424 425 426 427 428 |
/* * 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
|
429 |
if (__mnt_is_readonly(path.mnt)) |
6902d925d
|
430 |
res = -EROFS; |
1da177e4c
|
431 |
|
6902d925d
|
432 |
out_path_release: |
2d8f30380
|
433 |
path_put(&path); |
87fa55952
|
434 435 436 437 |
if (retry_estale(res, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
6902d925d
|
438 |
out: |
c8ffd8bcd
|
439 440 |
if (old_cred) revert_creds(old_cred); |
1da177e4c
|
441 442 |
return res; } |
cbfe20f56
|
443 444 |
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) { |
c8ffd8bcd
|
445 446 447 448 449 450 451 |
return do_faccessat(dfd, filename, mode, 0); } SYSCALL_DEFINE4(faccessat2, int, dfd, const char __user *, filename, int, mode, int, flags) { return do_faccessat(dfd, filename, mode, flags); |
cbfe20f56
|
452 |
} |
ca013e945
|
453 |
SYSCALL_DEFINE2(access, const char __user *, filename, int, mode) |
5590ff0d5
|
454 |
{ |
c8ffd8bcd
|
455 |
return do_faccessat(AT_FDCWD, filename, mode, 0); |
5590ff0d5
|
456 |
} |
db63f1e31
|
457 |
SYSCALL_DEFINE1(chdir, const char __user *, filename) |
1da177e4c
|
458 |
{ |
2d8f30380
|
459 |
struct path path; |
1da177e4c
|
460 |
int error; |
0291c0a55
|
461 462 463 |
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; retry: error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); |
1da177e4c
|
464 465 |
if (error) goto out; |
02f92b386
|
466 |
error = path_permission(&path, MAY_EXEC | MAY_CHDIR); |
1da177e4c
|
467 468 |
if (error) goto dput_and_out; |
2d8f30380
|
469 |
set_fs_pwd(current->fs, &path); |
1da177e4c
|
470 471 |
dput_and_out: |
2d8f30380
|
472 |
path_put(&path); |
0291c0a55
|
473 474 475 476 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
1da177e4c
|
477 478 479 |
out: return error; } |
3cdad4288
|
480 |
SYSCALL_DEFINE1(fchdir, unsigned int, fd) |
1da177e4c
|
481 |
{ |
2903ff019
|
482 |
struct fd f = fdget_raw(fd); |
159b09562
|
483 |
int error; |
1da177e4c
|
484 485 |
error = -EBADF; |
2903ff019
|
486 |
if (!f.file) |
1da177e4c
|
487 |
goto out; |
1da177e4c
|
488 |
error = -ENOTDIR; |
159b09562
|
489 |
if (!d_can_lookup(f.file->f_path.dentry)) |
1da177e4c
|
490 |
goto out_putf; |
02f92b386
|
491 |
error = file_permission(f.file, MAY_EXEC | MAY_CHDIR); |
1da177e4c
|
492 |
if (!error) |
2903ff019
|
493 |
set_fs_pwd(current->fs, &f.file->f_path); |
1da177e4c
|
494 |
out_putf: |
2903ff019
|
495 |
fdput(f); |
1da177e4c
|
496 497 498 |
out: return error; } |
4b7ca5014
|
499 |
SYSCALL_DEFINE1(chroot, const char __user *, filename) |
1da177e4c
|
500 |
{ |
2d8f30380
|
501 |
struct path path; |
1da177e4c
|
502 |
int error; |
2771261ec
|
503 504 505 |
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; retry: error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); |
1da177e4c
|
506 507 |
if (error) goto out; |
02f92b386
|
508 |
error = path_permission(&path, MAY_EXEC | MAY_CHDIR); |
1da177e4c
|
509 510 511 512 |
if (error) goto dput_and_out; error = -EPERM; |
c7b96acf1
|
513 |
if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT)) |
1da177e4c
|
514 |
goto dput_and_out; |
8b8efb440
|
515 516 517 |
error = security_path_chroot(&path); if (error) goto dput_and_out; |
1da177e4c
|
518 |
|
2d8f30380
|
519 |
set_fs_root(current->fs, &path); |
1da177e4c
|
520 521 |
error = 0; dput_and_out: |
2d8f30380
|
522 |
path_put(&path); |
2771261ec
|
523 524 525 526 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
1da177e4c
|
527 528 529 |
out: return error; } |
1097742ef
|
530 |
int chmod_common(const struct path *path, umode_t mode) |
1da177e4c
|
531 |
{ |
e57712ebe
|
532 |
struct inode *inode = path->dentry->d_inode; |
27ac0ffea
|
533 |
struct inode *delegated_inode = NULL; |
1da177e4c
|
534 |
struct iattr newattrs; |
e57712ebe
|
535 |
int error; |
1da177e4c
|
536 |
|
e57712ebe
|
537 538 539 |
error = mnt_want_write(path->mnt); if (error) return error; |
27ac0ffea
|
540 |
retry_deleg: |
5955102c9
|
541 |
inode_lock(inode); |
cdcf116d4
|
542 |
error = security_path_chmod(path, mode); |
e57712ebe
|
543 |
if (error) |
fe542cf59
|
544 |
goto out_unlock; |
1da177e4c
|
545 546 |
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
b8b546a06
|
547 548 |
error = notify_change(mnt_user_ns(path->mnt), path->dentry, &newattrs, &delegated_inode); |
fe542cf59
|
549 |
out_unlock: |
5955102c9
|
550 |
inode_unlock(inode); |
27ac0ffea
|
551 552 553 554 555 |
if (delegated_inode) { error = break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; } |
e57712ebe
|
556 557 558 |
mnt_drop_write(path->mnt); return error; } |
9e96c8c0e
|
559 560 561 562 563 |
int vfs_fchmod(struct file *file, umode_t mode) { audit_file(file); return chmod_common(&file->f_path, mode); } |
b25ba7c3c
|
564 |
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode) |
e57712ebe
|
565 |
{ |
173c84012
|
566 |
struct fd f = fdget(fd); |
e57712ebe
|
567 |
int err = -EBADF; |
173c84012
|
568 |
if (f.file) { |
9e96c8c0e
|
569 |
err = vfs_fchmod(f.file, mode); |
173c84012
|
570 |
fdput(f); |
e57712ebe
|
571 |
} |
1da177e4c
|
572 573 |
return err; } |
1097742ef
|
574 |
static int do_fchmodat(int dfd, const char __user *filename, umode_t mode) |
1da177e4c
|
575 |
{ |
2d8f30380
|
576 |
struct path path; |
1da177e4c
|
577 |
int error; |
14ff690c0
|
578 579 580 |
unsigned int lookup_flags = LOOKUP_FOLLOW; retry: error = user_path_at(dfd, filename, lookup_flags, &path); |
e57712ebe
|
581 582 583 |
if (!error) { error = chmod_common(&path, mode); path_put(&path); |
14ff690c0
|
584 585 586 587 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
e57712ebe
|
588 |
} |
1da177e4c
|
589 590 |
return error; } |
03450e271
|
591 592 593 594 595 |
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode) { return do_fchmodat(dfd, filename, mode); } |
49f0a0767
|
596 |
SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode) |
5590ff0d5
|
597 |
{ |
03450e271
|
598 |
return do_fchmodat(AT_FDCWD, filename, mode); |
5590ff0d5
|
599 |
} |
b873498f9
|
600 |
int chown_common(const struct path *path, uid_t user, gid_t group) |
1da177e4c
|
601 |
{ |
38753e917
|
602 |
struct user_namespace *mnt_userns, *fs_userns; |
fe542cf59
|
603 |
struct inode *inode = path->dentry->d_inode; |
27ac0ffea
|
604 |
struct inode *delegated_inode = NULL; |
1da177e4c
|
605 606 |
int error; struct iattr newattrs; |
52137abe1
|
607 608 609 610 611 |
kuid_t uid; kgid_t gid; uid = make_kuid(current_user_ns(), user); gid = make_kgid(current_user_ns(), group); |
1da177e4c
|
612 |
|
b8b546a06
|
613 |
mnt_userns = mnt_user_ns(path->mnt); |
38753e917
|
614 615 616 |
fs_userns = i_user_ns(inode); uid = mapped_kuid_user(mnt_userns, fs_userns, uid); gid = mapped_kgid_user(mnt_userns, fs_userns, gid); |
b8b546a06
|
617 |
|
c1b8940b4
|
618 |
retry_deleg: |
1da177e4c
|
619 620 |
newattrs.ia_valid = ATTR_CTIME; if (user != (uid_t) -1) { |
52137abe1
|
621 622 |
if (!uid_valid(uid)) return -EINVAL; |
1da177e4c
|
623 |
newattrs.ia_valid |= ATTR_UID; |
52137abe1
|
624 |
newattrs.ia_uid = uid; |
1da177e4c
|
625 626 |
} if (group != (gid_t) -1) { |
52137abe1
|
627 628 |
if (!gid_valid(gid)) return -EINVAL; |
1da177e4c
|
629 |
newattrs.ia_valid |= ATTR_GID; |
52137abe1
|
630 |
newattrs.ia_gid = gid; |
1da177e4c
|
631 632 |
} if (!S_ISDIR(inode->i_mode)) |
b53767719
|
633 634 |
newattrs.ia_valid |= ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV; |
5955102c9
|
635 |
inode_lock(inode); |
d2b31ca64
|
636 |
error = security_path_chown(path, uid, gid); |
fe542cf59
|
637 |
if (!error) |
b8b546a06
|
638 |
error = notify_change(mnt_userns, path->dentry, &newattrs, |
2f221d6f7
|
639 |
&delegated_inode); |
5955102c9
|
640 |
inode_unlock(inode); |
27ac0ffea
|
641 642 643 644 645 |
if (delegated_inode) { error = break_deleg_wait(&delegated_inode); if (!error) goto retry_deleg; } |
1da177e4c
|
646 647 |
return error; } |
55731b3cd
|
648 649 |
int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group, int flag) |
5590ff0d5
|
650 |
{ |
2d8f30380
|
651 |
struct path path; |
5590ff0d5
|
652 |
int error = -EINVAL; |
65cfc6722
|
653 |
int lookup_flags; |
5590ff0d5
|
654 |
|
65cfc6722
|
655 |
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0) |
5590ff0d5
|
656 |
goto out; |
65cfc6722
|
657 658 659 |
lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; if (flag & AT_EMPTY_PATH) lookup_flags |= LOOKUP_EMPTY; |
99a5df37a
|
660 |
retry: |
65cfc6722
|
661 |
error = user_path_at(dfd, filename, lookup_flags, &path); |
6902d925d
|
662 663 |
if (error) goto out; |
2d8f30380
|
664 |
error = mnt_want_write(path.mnt); |
2af482a7e
|
665 666 |
if (error) goto out_release; |
fe542cf59
|
667 |
error = chown_common(&path, user, group); |
2d8f30380
|
668 |
mnt_drop_write(path.mnt); |
2af482a7e
|
669 |
out_release: |
2d8f30380
|
670 |
path_put(&path); |
99a5df37a
|
671 672 673 674 |
if (retry_estale(error, lookup_flags)) { lookup_flags |= LOOKUP_REVAL; goto retry; } |
5590ff0d5
|
675 676 677 |
out: return error; } |
55731b3cd
|
678 679 680 681 682 |
SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, gid_t, group, int, flag) { return do_fchownat(dfd, filename, user, group, flag); } |
55e4def0a
|
683 |
SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) |
1da177e4c
|
684 |
{ |
55731b3cd
|
685 |
return do_fchownat(AT_FDCWD, filename, user, group, 0); |
55e4def0a
|
686 |
} |
1da177e4c
|
687 |
|
55e4def0a
|
688 689 |
SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group) { |
55731b3cd
|
690 691 |
return do_fchownat(AT_FDCWD, filename, user, group, AT_SYMLINK_NOFOLLOW); |
1da177e4c
|
692 |
} |
c04011fe8
|
693 694 695 696 697 698 699 700 701 702 703 704 |
int vfs_fchown(struct file *file, uid_t user, gid_t group) { int error; error = mnt_want_write_file(file); if (error) return error; audit_file(file); error = chown_common(&file->f_path, user, group); mnt_drop_write_file(file); return error; } |
55731b3cd
|
705 |
int ksys_fchown(unsigned int fd, uid_t user, gid_t group) |
1da177e4c
|
706 |
{ |
2903ff019
|
707 |
struct fd f = fdget(fd); |
1da177e4c
|
708 |
int error = -EBADF; |
c04011fe8
|
709 710 711 712 |
if (f.file) { error = vfs_fchown(f.file, user, group); fdput(f); } |
1da177e4c
|
713 714 |
return error; } |
55731b3cd
|
715 716 717 718 |
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) { return ksys_fchown(fd, user, group); } |
02e5180d9
|
719 |
static int do_dentry_open(struct file *f, |
4bacc9c92
|
720 |
struct inode *inode, |
ae2bb293a
|
721 |
int (*open)(struct inode *, struct file *)) |
1da177e4c
|
722 |
{ |
1abf0c718
|
723 |
static const struct file_operations empty_fops = {}; |
1da177e4c
|
724 |
int error; |
b5bcdda32
|
725 |
path_get(&f->f_path); |
4bacc9c92
|
726 |
f->f_inode = inode; |
1da177e4c
|
727 |
f->f_mapping = inode->i_mapping; |
5660e13d2
|
728 |
f->f_wb_err = filemap_sample_wb_err(f->f_mapping); |
735e4ae5b
|
729 |
f->f_sb_err = file_sample_sb_err(f); |
5660e13d2
|
730 |
|
3f4d5a000
|
731 |
if (unlikely(f->f_flags & O_PATH)) { |
f5d11409e
|
732 |
f->f_mode = FMODE_PATH | FMODE_OPENED; |
1abf0c718
|
733 |
f->f_op = &empty_fops; |
af04fadca
|
734 |
return 0; |
1abf0c718
|
735 |
} |
dd20908a8
|
736 |
if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) { |
0ccb28634
|
737 |
error = get_write_access(inode); |
3f4d5a000
|
738 |
if (unlikely(error)) |
1da177e4c
|
739 |
goto cleanup_file; |
0ccb28634
|
740 |
error = __mnt_want_write(f->f_path.mnt); |
3f4d5a000
|
741 |
if (unlikely(error)) { |
0ccb28634
|
742 743 744 |
put_write_access(inode); goto cleanup_file; } |
83f936c75
|
745 |
f->f_mode |= FMODE_WRITER; |
1da177e4c
|
746 |
} |
2be7d348f
|
747 748 749 |
/* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */ if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) f->f_mode |= FMODE_ATOMIC_POS; |
1abf0c718
|
750 |
f->f_op = fops_get(inode->i_fop); |
7159d5441
|
751 |
if (WARN_ON(!f->f_op)) { |
72c2d5319
|
752 753 754 |
error = -ENODEV; goto cleanup_all; } |
1abf0c718
|
755 |
|
e3f20ae21
|
756 |
error = security_file_open(f); |
788e7dd4c
|
757 758 |
if (error) goto cleanup_all; |
c568d6834
|
759 |
error = break_lease(locks_inode(f), f->f_flags); |
f3c7691e8
|
760 761 |
if (error) goto cleanup_all; |
ea73ea727
|
762 763 |
/* normally all 3 are set; ->open() can clear them if needed */ f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE; |
72c2d5319
|
764 |
if (!open) |
834f2a4a1
|
765 766 767 |
open = f->f_op->open; if (open) { error = open(inode, f); |
1da177e4c
|
768 769 770 |
if (error) goto cleanup_all; } |
f5d11409e
|
771 |
f->f_mode |= FMODE_OPENED; |
890275b5e
|
772 773 |
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) i_readcount_inc(inode); |
293bc9822
|
774 |
if ((f->f_mode & FMODE_READ) && |
843631820
|
775 |
likely(f->f_op->read || f->f_op->read_iter)) |
7f7f25e82
|
776 |
f->f_mode |= FMODE_CAN_READ; |
293bc9822
|
777 |
if ((f->f_mode & FMODE_WRITE) && |
843631820
|
778 |
likely(f->f_op->write || f->f_op->write_iter)) |
7f7f25e82
|
779 |
f->f_mode |= FMODE_CAN_WRITE; |
834f2a4a1
|
780 |
|
c75b1d942
|
781 |
f->f_write_hint = WRITE_LIFE_NOT_SET; |
1da177e4c
|
782 783 784 |
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); |
af04fadca
|
785 |
|
69527c554
|
786 787 788 789 790 |
/* NB: we're sure to have correct a_ops only after f_op->open */ if (f->f_flags & O_DIRECT) { if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO) return -EINVAL; } |
09d91cda0
|
791 792 793 794 795 |
/* * XXX: Huge page cache doesn't support writing yet. Drop all page * cache for this file before processing writes. */ |
eb6ecbed0
|
796 797 798 799 800 801 802 803 |
if (f->f_mode & FMODE_WRITE) { /* * Paired with smp_mb() in collapse_file() to ensure nr_thps * is up to date and the update to i_writecount by * get_write_access() is visible. Ensures subsequent insertion * of THPs into the page cache will fail. */ smp_mb(); |
fd8e972dc
|
804 |
if (filemap_nr_thps(inode->i_mapping)) { |
3ea871f0d
|
805 |
struct address_space *mapping = inode->i_mapping; |
fd8e972dc
|
806 |
filemap_invalidate_lock(inode->i_mapping); |
3ea871f0d
|
807 808 809 810 811 812 813 814 |
/* * unmap_mapping_range just need to be called once * here, because the private pages is not need to be * unmapped mapping (e.g. data segment of dynamic * shared libraries here). */ unmap_mapping_range(mapping, 0, 0, 0); truncate_inode_pages(mapping, 0); |
fd8e972dc
|
815 816 |
filemap_invalidate_unlock(inode->i_mapping); } |
eb6ecbed0
|
817 |
} |
09d91cda0
|
818 |
|
96b7e579a
|
819 |
return 0; |
1da177e4c
|
820 821 |
cleanup_all: |
6b4e8085c
|
822 823 |
if (WARN_ON_ONCE(error > 0)) error = -EINVAL; |
1da177e4c
|
824 |
fops_put(f->f_op); |
83f936c75
|
825 |
if (f->f_mode & FMODE_WRITER) { |
1da177e4c
|
826 |
put_write_access(inode); |
83f936c75
|
827 |
__mnt_drop_write(f->f_path.mnt); |
4a3fd211c
|
828 |
} |
1da177e4c
|
829 |
cleanup_file: |
02e5180d9
|
830 831 832 |
path_put(&f->f_path); f->f_path.mnt = NULL; f->f_path.dentry = NULL; |
dd37978c5
|
833 |
f->f_inode = NULL; |
96b7e579a
|
834 |
return error; |
1da177e4c
|
835 |
} |
834f2a4a1
|
836 |
/** |
d18e9008c
|
837 |
* finish_open - finish opening a file |
0854d450e
|
838 |
* @file: file pointer |
d18e9008c
|
839 840 |
* @dentry: pointer to dentry * @open: open callback |
0854d450e
|
841 |
* @opened: state of open |
d18e9008c
|
842 843 844 845 846 |
* * 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
|
847 848 849 850 851 |
* * 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(). * |
0854d450e
|
852 |
* Returns zero on success or -errno if the open failed. |
d18e9008c
|
853 |
*/ |
30d904947
|
854 |
int finish_open(struct file *file, struct dentry *dentry, |
be12af3ef
|
855 |
int (*open)(struct inode *, struct file *)) |
d18e9008c
|
856 |
{ |
aad888f82
|
857 |
BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */ |
d18e9008c
|
858 |
|
b5bcdda32
|
859 |
file->f_path.dentry = dentry; |
aad888f82
|
860 |
return do_dentry_open(file, d_backing_inode(dentry), open); |
d18e9008c
|
861 862 863 864 865 866 |
} EXPORT_SYMBOL(finish_open); /** * finish_no_open - finish ->atomic_open() without opening the file * |
0854d450e
|
867 |
* @file: file pointer |
d18e9008c
|
868 869 870 |
* @dentry: dentry or NULL (as returned from ->lookup()) * * This can be used to set the result of a successful lookup in ->atomic_open(). |
0854d450e
|
871 872 873 874 |
* * NB: unlike finish_open() this function does consume the dentry reference and * the caller need not dput() it. * |
64e1ac4d4
|
875 |
* Returns "0" which must be the return value of ->atomic_open() after having |
0854d450e
|
876 |
* called this function. |
d18e9008c
|
877 |
*/ |
e45198a6a
|
878 |
int finish_no_open(struct file *file, struct dentry *dentry) |
d18e9008c
|
879 |
{ |
30d904947
|
880 |
file->f_path.dentry = dentry; |
64e1ac4d4
|
881 |
return 0; |
d18e9008c
|
882 883 |
} EXPORT_SYMBOL(finish_no_open); |
9bf39ab2a
|
884 885 886 887 888 |
char *file_path(struct file *filp, char *buf, int buflen) { return d_path(&filp->f_path, buf, buflen); } EXPORT_SYMBOL(file_path); |
4bacc9c92
|
889 890 891 892 893 894 |
/** * 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 */ |
ae2bb293a
|
895 |
int vfs_open(const struct path *path, struct file *file) |
4bacc9c92
|
896 |
{ |
54d5ca871
|
897 |
file->f_path = *path; |
a6518f73e
|
898 |
return do_dentry_open(file, d_backing_inode(path->dentry), NULL); |
4bacc9c92
|
899 |
} |
765927b2d
|
900 |
struct file *dentry_open(const struct path *path, int flags, |
745ca2475
|
901 |
const struct cred *cred) |
a1a5b3d93
|
902 903 904 |
{ int error; struct file *f; |
e0e817392
|
905 |
validate_creds(cred); |
c212f9aaf
|
906 |
/* We must always pass in a valid mount pointer. */ |
765927b2d
|
907 |
BUG_ON(!path->mnt); |
322ee5b36
|
908 |
|
ea73ea727
|
909 |
f = alloc_empty_file(flags, cred); |
af04fadca
|
910 |
if (!IS_ERR(f)) { |
ae2bb293a
|
911 |
error = vfs_open(path, f); |
4d27f3266
|
912 913 |
if (error) { fput(f); |
af04fadca
|
914 915 |
f = ERR_PTR(error); } |
2a027e7a1
|
916 917 |
} return f; |
a1a5b3d93
|
918 |
} |
1da177e4c
|
919 |
EXPORT_SYMBOL(dentry_open); |
2abc77af8
|
920 921 922 |
struct file *open_with_fake_path(const struct path *path, int flags, struct inode *inode, const struct cred *cred) { |
d3b1084df
|
923 |
struct file *f = alloc_empty_file_noaccount(flags, cred); |
2abc77af8
|
924 925 926 927 928 929 930 931 932 933 934 935 936 |
if (!IS_ERR(f)) { int error; f->f_path = *path; error = do_dentry_open(f, inode, NULL); if (error) { fput(f); f = ERR_PTR(error); } } return f; } EXPORT_SYMBOL(open_with_fake_path); |
fddb5d430
|
937 938 |
#define WILL_CREATE(flags) (flags & (O_CREAT | __O_TMPFILE)) #define O_PATH_FLAGS (O_DIRECTORY | O_NOFOLLOW | O_PATH | O_CLOEXEC) |
35cb6d54c
|
939 |
inline struct open_how build_open_how(int flags, umode_t mode) |
fddb5d430
|
940 941 942 943 944 945 946 947 948 949 950 951 952 953 |
{ struct open_how how = { .flags = flags & VALID_OPEN_FLAGS, .mode = mode & S_IALLUGO, }; /* O_PATH beats everything else. */ if (how.flags & O_PATH) how.flags &= O_PATH_FLAGS; /* Modes should only be set for create-like flags. */ if (!WILL_CREATE(how.flags)) how.mode = 0; return how; } |
35cb6d54c
|
954 |
inline int build_open_flags(const struct open_how *how, struct open_flags *op) |
47c805dc2
|
955 |
{ |
cfe80306a
|
956 957 |
u64 flags = how->flags; u64 strip = FMODE_NONOTIFY | O_CLOEXEC; |
47c805dc2
|
958 |
int lookup_flags = 0; |
62fb4a155
|
959 |
int acc_mode = ACC_MODE(flags); |
47c805dc2
|
960 |
|
cfe80306a
|
961 962 963 964 965 966 967 968 969 |
BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS), "struct open_flags doesn't yet handle flags > 32 bits"); /* * Strip flags that either shouldn't be set by userspace like * FMODE_NONOTIFY or that aren't relevant in determining struct * open_flags like O_CLOEXEC. */ flags &= ~strip; |
fddb5d430
|
970 |
|
629e014bb
|
971 |
/* |
fddb5d430
|
972 973 974 |
* Older syscalls implicitly clear all of the invalid flags or argument * values before calling build_open_flags(), but openat2(2) checks all * of its arguments. |
629e014bb
|
975 |
*/ |
fddb5d430
|
976 977 978 979 |
if (flags & ~VALID_OPEN_FLAGS) return -EINVAL; if (how->resolve & ~VALID_RESOLVE_FLAGS) return -EINVAL; |
629e014bb
|
980 |
|
398840f8b
|
981 982 983 |
/* Scoping flags are mutually exclusive. */ if ((how->resolve & RESOLVE_BENEATH) && (how->resolve & RESOLVE_IN_ROOT)) return -EINVAL; |
fddb5d430
|
984 985 986 987 988 989 990 991 |
/* Deal with the mode. */ if (WILL_CREATE(flags)) { if (how->mode & ~S_IALLUGO) return -EINVAL; op->mode = how->mode | S_IFREG; } else { if (how->mode != 0) return -EINVAL; |
e68726ff7
|
992 |
op->mode = 0; |
fddb5d430
|
993 |
} |
47c805dc2
|
994 995 |
/* |
fddb5d430
|
996 997 998 999 |
* In order to ensure programs get explicit errors when trying to use * O_TMPFILE on old kernels, O_TMPFILE is implemented such that it * looks like (O_DIRECTORY|O_RDWR & ~O_CREAT) to old kernels. But we * have to require userspace to explicitly set it. |
47c805dc2
|
1000 |
*/ |
bb458c644
|
1001 1002 |
if (flags & __O_TMPFILE) { if ((flags & O_TMPFILE_MASK) != O_TMPFILE) |
60545d0d4
|
1003 |
return -EINVAL; |
ba57ea64c
|
1004 1005 |
if (!(acc_mode & MAY_WRITE)) return -EINVAL; |
fddb5d430
|
1006 1007 1008 1009 1010 |
} if (flags & O_PATH) { /* O_PATH only permits certain other flags to be set. */ if (flags & ~O_PATH_FLAGS) return -EINVAL; |
1abf0c718
|
1011 |
acc_mode = 0; |
1abf0c718
|
1012 |
} |
47c805dc2
|
1013 |
|
fddb5d430
|
1014 1015 1016 1017 1018 1019 1020 1021 |
/* * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only * check for O_DSYNC if the need any syncing at all we enforce it's * always set instead of having to deal with possibly weird behaviour * for malicious applications setting only __O_SYNC. */ if (flags & __O_SYNC) flags |= O_DSYNC; |
1abf0c718
|
1022 |
op->open_flag = flags; |
47c805dc2
|
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 |
/* 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
|
1034 |
op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN; |
47c805dc2
|
1035 1036 |
if (flags & O_CREAT) { op->intent |= LOOKUP_CREATE; |
31d1726d7
|
1037 |
if (flags & O_EXCL) { |
47c805dc2
|
1038 |
op->intent |= LOOKUP_EXCL; |
31d1726d7
|
1039 1040 |
flags |= O_NOFOLLOW; } |
47c805dc2
|
1041 1042 1043 1044 1045 1046 |
} if (flags & O_DIRECTORY) lookup_flags |= LOOKUP_DIRECTORY; if (!(flags & O_NOFOLLOW)) lookup_flags |= LOOKUP_FOLLOW; |
fddb5d430
|
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 |
if (how->resolve & RESOLVE_NO_XDEV) lookup_flags |= LOOKUP_NO_XDEV; if (how->resolve & RESOLVE_NO_MAGICLINKS) lookup_flags |= LOOKUP_NO_MAGICLINKS; if (how->resolve & RESOLVE_NO_SYMLINKS) lookup_flags |= LOOKUP_NO_SYMLINKS; if (how->resolve & RESOLVE_BENEATH) lookup_flags |= LOOKUP_BENEATH; if (how->resolve & RESOLVE_IN_ROOT) lookup_flags |= LOOKUP_IN_ROOT; |
99668f618
|
1058 1059 1060 1061 1062 1063 |
if (how->resolve & RESOLVE_CACHED) { /* Don't bother even trying for create/truncate/tmpfile open */ if (flags & (O_TRUNC | O_CREAT | O_TMPFILE)) return -EAGAIN; lookup_flags |= LOOKUP_CACHED; } |
fddb5d430
|
1064 |
|
f9652e10c
|
1065 1066 |
op->lookup_flags = lookup_flags; return 0; |
47c805dc2
|
1067 1068 1069 |
} /** |
669abf4e5
|
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 |
* 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; |
fddb5d430
|
1083 1084 1085 1086 1087 |
struct open_how how = build_open_how(flags, mode); int err = build_open_flags(&how, &op); if (err) return ERR_PTR(err); return do_filp_open(AT_FDCWD, name, &op); |
669abf4e5
|
1088 1089 1090 |
} /** |
47c805dc2
|
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 |
* 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
|
1101 |
struct file *filp_open(const char *filename, int flags, umode_t mode) |
47c805dc2
|
1102 |
{ |
516891041
|
1103 1104 1105 1106 1107 1108 1109 1110 |
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
|
1111 1112 |
} EXPORT_SYMBOL(filp_open); |
ffb37ca3b
|
1113 |
struct file *file_open_root(const struct path *root, |
378c6520e
|
1114 |
const char *filename, int flags, umode_t mode) |
73d049a40
|
1115 1116 |
{ struct open_flags op; |
fddb5d430
|
1117 1118 |
struct open_how how = build_open_how(flags, mode); int err = build_open_flags(&how, &op); |
f9652e10c
|
1119 1120 |
if (err) return ERR_PTR(err); |
ffb37ca3b
|
1121 |
return do_file_open_root(root, filename, &op); |
73d049a40
|
1122 1123 |
} EXPORT_SYMBOL(file_open_root); |
fddb5d430
|
1124 1125 |
static long do_sys_openat2(int dfd, const char __user *filename, struct open_how *how) |
1da177e4c
|
1126 |
{ |
47c805dc2
|
1127 |
struct open_flags op; |
fddb5d430
|
1128 |
int fd = build_open_flags(how, &op); |
f9652e10c
|
1129 1130 1131 1132 1133 1134 1135 1136 |
struct filename *tmp; if (fd) return fd; tmp = getname(filename); if (IS_ERR(tmp)) return PTR_ERR(tmp); |
fddb5d430
|
1137 |
fd = get_unused_fd_flags(how->flags); |
f9652e10c
|
1138 1139 1140 1141 1142 1143 1144 1145 |
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
|
1146 |
} |
1da177e4c
|
1147 |
} |
f9652e10c
|
1148 |
putname(tmp); |
1da177e4c
|
1149 |
return fd; |
1da177e4c
|
1150 |
} |
e922efc34
|
1151 |
|
fddb5d430
|
1152 |
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) |
e922efc34
|
1153 |
{ |
fddb5d430
|
1154 1155 1156 |
struct open_how how = build_open_how(flags, mode); return do_sys_openat2(dfd, filename, &how); } |
e922efc34
|
1157 |
|
fddb5d430
|
1158 1159 1160 |
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) { |
166e07c37
|
1161 1162 1163 |
if (force_o_largefile()) flags |= O_LARGEFILE; return do_sys_open(AT_FDCWD, filename, flags, mode); |
e922efc34
|
1164 |
} |
1da177e4c
|
1165 |
|
6559eed8c
|
1166 |
SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, |
a218d0fdc
|
1167 |
umode_t, mode) |
5590ff0d5
|
1168 1169 1170 |
{ if (force_o_largefile()) flags |= O_LARGEFILE; |
2cf096668
|
1171 |
return do_sys_open(dfd, filename, flags, mode); |
5590ff0d5
|
1172 |
} |
5590ff0d5
|
1173 |
|
fddb5d430
|
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 |
SYSCALL_DEFINE4(openat2, int, dfd, const char __user *, filename, struct open_how __user *, how, size_t, usize) { int err; struct open_how tmp; BUILD_BUG_ON(sizeof(struct open_how) < OPEN_HOW_SIZE_VER0); BUILD_BUG_ON(sizeof(struct open_how) != OPEN_HOW_SIZE_LATEST); if (unlikely(usize < OPEN_HOW_SIZE_VER0)) return -EINVAL; err = copy_struct_from_user(&tmp, sizeof(tmp), how, usize); if (err) return err; /* O_LARGEFILE is only allowed for non-O_PATH. */ if (!(tmp.flags & O_PATH) && force_o_largefile()) tmp.flags |= O_LARGEFILE; return do_sys_openat2(dfd, filename, &tmp); } |
e35d49f63
|
1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 |
#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
|
1215 1216 1217 1218 1219 1220 |
#ifndef __alpha__ /* * For backward compatibility? Maybe this should be moved * into arch/i386 instead? */ |
a218d0fdc
|
1221 |
SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode) |
1da177e4c
|
1222 |
{ |
166e07c37
|
1223 |
int flags = O_CREAT | O_WRONLY | O_TRUNC; |
1da177e4c
|
1224 |
|
166e07c37
|
1225 1226 1227 1228 |
if (force_o_largefile()) flags |= O_LARGEFILE; return do_sys_open(AT_FDCWD, pathname, flags, mode); } |
1da177e4c
|
1229 1230 1231 1232 1233 1234 1235 1236 |
#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
|
1237 |
int retval = 0; |
1da177e4c
|
1238 1239 1240 1241 |
if (!file_count(filp)) { printk(KERN_ERR "VFS: Close: file count is 0 "); |
45778ca81
|
1242 |
return 0; |
1da177e4c
|
1243 |
} |
72c2d5319
|
1244 |
if (filp->f_op->flush) |
75e1fcc0b
|
1245 |
retval = filp->f_op->flush(filp, id); |
1da177e4c
|
1246 |
|
1abf0c718
|
1247 1248 1249 1250 |
if (likely(!(filp->f_mode & FMODE_PATH))) { dnotify_flush(filp, id); locks_remove_posix(filp, id); } |
1da177e4c
|
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 |
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
|
1262 |
SYSCALL_DEFINE1(close, unsigned int, fd) |
1da177e4c
|
1263 |
{ |
8760c909f
|
1264 |
int retval = close_fd(fd); |
ee731f4f7
|
1265 1266 1267 1268 1269 1270 1271 1272 1273 |
/* 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
|
1274 |
} |
1da177e4c
|
1275 |
|
278a5fbae
|
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 |
/** * close_range() - Close all file descriptors in a given range. * * @fd: starting file descriptor to close * @max_fd: last file descriptor to close * @flags: reserved for future extensions * * This closes a range of file descriptors. All file descriptors * from @fd up to and including @max_fd are closed. * Currently, errors to close a given file descriptor are ignored. */ SYSCALL_DEFINE3(close_range, unsigned int, fd, unsigned int, max_fd, unsigned int, flags) { |
60997c3d4
|
1290 |
return __close_range(fd, max_fd, flags); |
278a5fbae
|
1291 |
} |
1da177e4c
|
1292 1293 1294 1295 |
/* * This routine simulates a hangup on the tty, to arrange that users * are given clean terminals at login time. */ |
ca013e945
|
1296 |
SYSCALL_DEFINE0(vhangup) |
1da177e4c
|
1297 1298 |
{ if (capable(CAP_SYS_TTY_CONFIG)) { |
2cb5998b5
|
1299 |
tty_vhangup_self(); |
1da177e4c
|
1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 |
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
|
1314 |
return -EOVERFLOW; |
1da177e4c
|
1315 1316 1317 1318 1319 1320 1321 |
return 0; } EXPORT_SYMBOL(generic_file_open); /* * This is used by subsystems that don't want seekable |
06b1e104b
|
1322 1323 1324 |
* 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
|
1325 1326 1327 1328 1329 1330 1331 1332 |
*/ int nonseekable_open(struct inode *inode, struct file *filp) { filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE); return 0; } EXPORT_SYMBOL(nonseekable_open); |
10dce8af3
|
1333 1334 1335 1336 |
/* * stream_open is used by subsystems that want stream-like file descriptors. * Such file descriptors are not seekable and don't have notion of position |
438ab720c
|
1337 1338 1339 |
* (file.f_pos is always 0 and ppos passed to .read()/.write() is always NULL). * Contrary to file descriptors of other regular files, .read() and .write() * can run simultaneously. |
10dce8af3
|
1340 1341 1342 1343 1344 1345 |
* * stream_open never fails and is marked to return int so that it could be * directly used as file_operations.open . */ int stream_open(struct inode *inode, struct file *filp) { |
2be7d348f
|
1346 |
filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS); |
10dce8af3
|
1347 1348 1349 1350 1351 |
filp->f_mode |= FMODE_STREAM; return 0; } EXPORT_SYMBOL(stream_open); |