diff options
author | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 04:48:30 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-01-29 04:48:30 -0500 |
commit | 617677295b53a40d0e54aac4cbbc216ffbc755dd (patch) | |
tree | 51b9e87213243ed5efff252c8e8d8fec4eebc588 /fs/open.c | |
parent | 5c8d1b68e01a144813e38795fe6dbe7ebb506131 (diff) | |
parent | 6abb7c25775b7fb2225ad0508236d63ca710e65f (diff) |
Merge branch 'master' into for-next
Conflicts:
drivers/devfreq/exynos4_bus.c
Sync with Linus' tree to be able to apply patches that are
against newer code (mvneta).
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 99 |
1 files changed, 67 insertions, 32 deletions
@@ -61,33 +61,22 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, | |||
61 | return ret; | 61 | return ret; |
62 | } | 62 | } |
63 | 63 | ||
64 | static long do_sys_truncate(const char __user *pathname, loff_t length) | 64 | long vfs_truncate(struct path *path, loff_t length) |
65 | { | 65 | { |
66 | struct path path; | ||
67 | struct inode *inode; | 66 | struct inode *inode; |
68 | int error; | 67 | long error; |
69 | |||
70 | error = -EINVAL; | ||
71 | if (length < 0) /* sorry, but loff_t says... */ | ||
72 | goto out; | ||
73 | 68 | ||
74 | error = user_path(pathname, &path); | 69 | inode = path->dentry->d_inode; |
75 | if (error) | ||
76 | goto out; | ||
77 | inode = path.dentry->d_inode; | ||
78 | 70 | ||
79 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ | 71 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ |
80 | error = -EISDIR; | ||
81 | if (S_ISDIR(inode->i_mode)) | 72 | if (S_ISDIR(inode->i_mode)) |
82 | goto dput_and_out; | 73 | return -EISDIR; |
83 | |||
84 | error = -EINVAL; | ||
85 | if (!S_ISREG(inode->i_mode)) | 74 | if (!S_ISREG(inode->i_mode)) |
86 | goto dput_and_out; | 75 | return -EINVAL; |
87 | 76 | ||
88 | error = mnt_want_write(path.mnt); | 77 | error = mnt_want_write(path->mnt); |
89 | if (error) | 78 | if (error) |
90 | goto dput_and_out; | 79 | goto out; |
91 | 80 | ||
92 | error = inode_permission(inode, MAY_WRITE); | 81 | error = inode_permission(inode, MAY_WRITE); |
93 | if (error) | 82 | if (error) |
@@ -111,19 +100,40 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
111 | 100 | ||
112 | error = locks_verify_truncate(inode, NULL, length); | 101 | error = locks_verify_truncate(inode, NULL, length); |
113 | if (!error) | 102 | if (!error) |
114 | error = security_path_truncate(&path); | 103 | error = security_path_truncate(path); |
115 | if (!error) | 104 | if (!error) |
116 | error = do_truncate(path.dentry, length, 0, NULL); | 105 | error = do_truncate(path->dentry, length, 0, NULL); |
117 | 106 | ||
118 | put_write_and_out: | 107 | put_write_and_out: |
119 | put_write_access(inode); | 108 | put_write_access(inode); |
120 | mnt_drop_write_and_out: | 109 | mnt_drop_write_and_out: |
121 | mnt_drop_write(path.mnt); | 110 | mnt_drop_write(path->mnt); |
122 | dput_and_out: | ||
123 | path_put(&path); | ||
124 | out: | 111 | out: |
125 | return error; | 112 | return error; |
126 | } | 113 | } |
114 | EXPORT_SYMBOL_GPL(vfs_truncate); | ||
115 | |||
116 | static long do_sys_truncate(const char __user *pathname, loff_t length) | ||
117 | { | ||
118 | unsigned int lookup_flags = LOOKUP_FOLLOW; | ||
119 | struct path path; | ||
120 | int error; | ||
121 | |||
122 | if (length < 0) /* sorry, but loff_t says... */ | ||
123 | return -EINVAL; | ||
124 | |||
125 | retry: | ||
126 | error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path); | ||
127 | if (!error) { | ||
128 | error = vfs_truncate(&path, length); | ||
129 | path_put(&path); | ||
130 | } | ||
131 | if (retry_estale(error, lookup_flags)) { | ||
132 | lookup_flags |= LOOKUP_REVAL; | ||
133 | goto retry; | ||
134 | } | ||
135 | return error; | ||
136 | } | ||
127 | 137 | ||
128 | SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) | 138 | SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) |
129 | { | 139 | { |
@@ -306,6 +316,7 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) | |||
306 | struct path path; | 316 | struct path path; |
307 | struct inode *inode; | 317 | struct inode *inode; |
308 | int res; | 318 | int res; |
319 | unsigned int lookup_flags = LOOKUP_FOLLOW; | ||
309 | 320 | ||
310 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ | 321 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ |
311 | return -EINVAL; | 322 | return -EINVAL; |
@@ -328,8 +339,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) | |||
328 | } | 339 | } |
329 | 340 | ||
330 | old_cred = override_creds(override_cred); | 341 | old_cred = override_creds(override_cred); |
331 | 342 | retry: | |
332 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); | 343 | res = user_path_at(dfd, filename, lookup_flags, &path); |
333 | if (res) | 344 | if (res) |
334 | goto out; | 345 | goto out; |
335 | 346 | ||
@@ -364,6 +375,10 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) | |||
364 | 375 | ||
365 | out_path_release: | 376 | out_path_release: |
366 | path_put(&path); | 377 | path_put(&path); |
378 | if (retry_estale(res, lookup_flags)) { | ||
379 | lookup_flags |= LOOKUP_REVAL; | ||
380 | goto retry; | ||
381 | } | ||
367 | out: | 382 | out: |
368 | revert_creds(old_cred); | 383 | revert_creds(old_cred); |
369 | put_cred(override_cred); | 384 | put_cred(override_cred); |
@@ -379,8 +394,9 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename) | |||
379 | { | 394 | { |
380 | struct path path; | 395 | struct path path; |
381 | int error; | 396 | int error; |
382 | 397 | unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; | |
383 | error = user_path_dir(filename, &path); | 398 | retry: |
399 | error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); | ||
384 | if (error) | 400 | if (error) |
385 | goto out; | 401 | goto out; |
386 | 402 | ||
@@ -392,6 +408,10 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename) | |||
392 | 408 | ||
393 | dput_and_out: | 409 | dput_and_out: |
394 | path_put(&path); | 410 | path_put(&path); |
411 | if (retry_estale(error, lookup_flags)) { | ||
412 | lookup_flags |= LOOKUP_REVAL; | ||
413 | goto retry; | ||
414 | } | ||
395 | out: | 415 | out: |
396 | return error; | 416 | return error; |
397 | } | 417 | } |
@@ -425,8 +445,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) | |||
425 | { | 445 | { |
426 | struct path path; | 446 | struct path path; |
427 | int error; | 447 | int error; |
428 | 448 | unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; | |
429 | error = user_path_dir(filename, &path); | 449 | retry: |
450 | error = user_path_at(AT_FDCWD, filename, lookup_flags, &path); | ||
430 | if (error) | 451 | if (error) |
431 | goto out; | 452 | goto out; |
432 | 453 | ||
@@ -435,7 +456,7 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) | |||
435 | goto dput_and_out; | 456 | goto dput_and_out; |
436 | 457 | ||
437 | error = -EPERM; | 458 | error = -EPERM; |
438 | if (!capable(CAP_SYS_CHROOT)) | 459 | if (!nsown_capable(CAP_SYS_CHROOT)) |
439 | goto dput_and_out; | 460 | goto dput_and_out; |
440 | error = security_path_chroot(&path); | 461 | error = security_path_chroot(&path); |
441 | if (error) | 462 | if (error) |
@@ -445,6 +466,10 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) | |||
445 | error = 0; | 466 | error = 0; |
446 | dput_and_out: | 467 | dput_and_out: |
447 | path_put(&path); | 468 | path_put(&path); |
469 | if (retry_estale(error, lookup_flags)) { | ||
470 | lookup_flags |= LOOKUP_REVAL; | ||
471 | goto retry; | ||
472 | } | ||
448 | out: | 473 | out: |
449 | return error; | 474 | return error; |
450 | } | 475 | } |
@@ -489,11 +514,16 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, umode_t, mode | |||
489 | { | 514 | { |
490 | struct path path; | 515 | struct path path; |
491 | int error; | 516 | int error; |
492 | 517 | unsigned int lookup_flags = LOOKUP_FOLLOW; | |
493 | error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); | 518 | retry: |
519 | error = user_path_at(dfd, filename, lookup_flags, &path); | ||
494 | if (!error) { | 520 | if (!error) { |
495 | error = chmod_common(&path, mode); | 521 | error = chmod_common(&path, mode); |
496 | path_put(&path); | 522 | path_put(&path); |
523 | if (retry_estale(error, lookup_flags)) { | ||
524 | lookup_flags |= LOOKUP_REVAL; | ||
525 | goto retry; | ||
526 | } | ||
497 | } | 527 | } |
498 | return error; | 528 | return error; |
499 | } | 529 | } |
@@ -552,6 +582,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, | |||
552 | lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; | 582 | lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; |
553 | if (flag & AT_EMPTY_PATH) | 583 | if (flag & AT_EMPTY_PATH) |
554 | lookup_flags |= LOOKUP_EMPTY; | 584 | lookup_flags |= LOOKUP_EMPTY; |
585 | retry: | ||
555 | error = user_path_at(dfd, filename, lookup_flags, &path); | 586 | error = user_path_at(dfd, filename, lookup_flags, &path); |
556 | if (error) | 587 | if (error) |
557 | goto out; | 588 | goto out; |
@@ -562,6 +593,10 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, | |||
562 | mnt_drop_write(path.mnt); | 593 | mnt_drop_write(path.mnt); |
563 | out_release: | 594 | out_release: |
564 | path_put(&path); | 595 | path_put(&path); |
596 | if (retry_estale(error, lookup_flags)) { | ||
597 | lookup_flags |= LOOKUP_REVAL; | ||
598 | goto retry; | ||
599 | } | ||
565 | out: | 600 | out: |
566 | return error; | 601 | return error; |
567 | } | 602 | } |