diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-07 16:00:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-08-07 16:00:23 -0400 |
commit | 8ef9c292ac7bf91fc0367746cf5db264adddced9 (patch) | |
tree | 61ab727e8d0fa4bf058c0d914b95e9f40d1ede33 /fs | |
parent | e4ef108fcde0b97ed38923ba1ea06c7a152bab9e (diff) | |
parent | 3d62c45b38e534262d443b5820fb06a0e6d0d42f (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
vfs: add missing check for __O_TMPFILE in fcntl_init()
fs: Allow unprivileged linkat(..., AT_EMPTY_PATH) aka flink
fs: Fix file mode for O_TMPFILE
reiserfs: fix deadlock in umount
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fcntl.c | 4 | ||||
-rw-r--r-- | fs/namei.c | 10 | ||||
-rw-r--r-- | fs/open.c | 2 | ||||
-rw-r--r-- | fs/reiserfs/procfs.c | 99 | ||||
-rw-r--r-- | fs/reiserfs/super.c | 3 |
5 files changed, 26 insertions, 92 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index 6599222536eb..65343c3741ff 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -730,14 +730,14 @@ static int __init fcntl_init(void) | |||
730 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY | 730 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY |
731 | * is defined as O_NONBLOCK on some platforms and not on others. | 731 | * is defined as O_NONBLOCK on some platforms and not on others. |
732 | */ | 732 | */ |
733 | BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( | 733 | BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( |
734 | O_RDONLY | O_WRONLY | O_RDWR | | 734 | O_RDONLY | O_WRONLY | O_RDWR | |
735 | O_CREAT | O_EXCL | O_NOCTTY | | 735 | O_CREAT | O_EXCL | O_NOCTTY | |
736 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ | 736 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ |
737 | __O_SYNC | O_DSYNC | FASYNC | | 737 | __O_SYNC | O_DSYNC | FASYNC | |
738 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | | 738 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | |
739 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | | 739 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | |
740 | __FMODE_EXEC | O_PATH | 740 | __FMODE_EXEC | O_PATH | __O_TMPFILE |
741 | )); | 741 | )); |
742 | 742 | ||
743 | fasync_cache = kmem_cache_create("fasync_cache", | 743 | fasync_cache = kmem_cache_create("fasync_cache", |
diff --git a/fs/namei.c b/fs/namei.c index 8b61d103a8a7..89a612e392eb 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -3671,15 +3671,11 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, | |||
3671 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) | 3671 | if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0) |
3672 | return -EINVAL; | 3672 | return -EINVAL; |
3673 | /* | 3673 | /* |
3674 | * To use null names we require CAP_DAC_READ_SEARCH | 3674 | * Using empty names is equivalent to using AT_SYMLINK_FOLLOW |
3675 | * This ensures that not everyone will be able to create | 3675 | * on /proc/self/fd/<fd>. |
3676 | * handlink using the passed filedescriptor. | ||
3677 | */ | 3676 | */ |
3678 | if (flags & AT_EMPTY_PATH) { | 3677 | if (flags & AT_EMPTY_PATH) |
3679 | if (!capable(CAP_DAC_READ_SEARCH)) | ||
3680 | return -ENOENT; | ||
3681 | how = LOOKUP_EMPTY; | 3678 | how = LOOKUP_EMPTY; |
3682 | } | ||
3683 | 3679 | ||
3684 | if (flags & AT_SYMLINK_FOLLOW) | 3680 | if (flags & AT_SYMLINK_FOLLOW) |
3685 | how |= LOOKUP_FOLLOW; | 3681 | how |= LOOKUP_FOLLOW; |
@@ -823,7 +823,7 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
823 | int lookup_flags = 0; | 823 | int lookup_flags = 0; |
824 | int acc_mode; | 824 | int acc_mode; |
825 | 825 | ||
826 | if (flags & O_CREAT) | 826 | if (flags & (O_CREAT | __O_TMPFILE)) |
827 | op->mode = (mode & S_IALLUGO) | S_IFREG; | 827 | op->mode = (mode & S_IALLUGO) | S_IFREG; |
828 | else | 828 | else |
829 | op->mode = 0; | 829 | op->mode = 0; |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index 33532f79b4f7..a958444a75fc 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
@@ -19,12 +19,13 @@ | |||
19 | /* | 19 | /* |
20 | * LOCKING: | 20 | * LOCKING: |
21 | * | 21 | * |
22 | * We rely on new Alexander Viro's super-block locking. | 22 | * These guys are evicted from procfs as the very first step in ->kill_sb(). |
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | 25 | ||
26 | static int show_version(struct seq_file *m, struct super_block *sb) | 26 | static int show_version(struct seq_file *m, void *unused) |
27 | { | 27 | { |
28 | struct super_block *sb = m->private; | ||
28 | char *format; | 29 | char *format; |
29 | 30 | ||
30 | if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) { | 31 | if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) { |
@@ -66,8 +67,9 @@ static int show_version(struct seq_file *m, struct super_block *sb) | |||
66 | #define DJP( x ) le32_to_cpu( jp -> x ) | 67 | #define DJP( x ) le32_to_cpu( jp -> x ) |
67 | #define JF( x ) ( r -> s_journal -> x ) | 68 | #define JF( x ) ( r -> s_journal -> x ) |
68 | 69 | ||
69 | static int show_super(struct seq_file *m, struct super_block *sb) | 70 | static int show_super(struct seq_file *m, void *unused) |
70 | { | 71 | { |
72 | struct super_block *sb = m->private; | ||
71 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 73 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
72 | 74 | ||
73 | seq_printf(m, "state: \t%s\n" | 75 | seq_printf(m, "state: \t%s\n" |
@@ -128,8 +130,9 @@ static int show_super(struct seq_file *m, struct super_block *sb) | |||
128 | return 0; | 130 | return 0; |
129 | } | 131 | } |
130 | 132 | ||
131 | static int show_per_level(struct seq_file *m, struct super_block *sb) | 133 | static int show_per_level(struct seq_file *m, void *unused) |
132 | { | 134 | { |
135 | struct super_block *sb = m->private; | ||
133 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 136 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
134 | int level; | 137 | int level; |
135 | 138 | ||
@@ -186,8 +189,9 @@ static int show_per_level(struct seq_file *m, struct super_block *sb) | |||
186 | return 0; | 189 | return 0; |
187 | } | 190 | } |
188 | 191 | ||
189 | static int show_bitmap(struct seq_file *m, struct super_block *sb) | 192 | static int show_bitmap(struct seq_file *m, void *unused) |
190 | { | 193 | { |
194 | struct super_block *sb = m->private; | ||
191 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 195 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
192 | 196 | ||
193 | seq_printf(m, "free_block: %lu\n" | 197 | seq_printf(m, "free_block: %lu\n" |
@@ -218,8 +222,9 @@ static int show_bitmap(struct seq_file *m, struct super_block *sb) | |||
218 | return 0; | 222 | return 0; |
219 | } | 223 | } |
220 | 224 | ||
221 | static int show_on_disk_super(struct seq_file *m, struct super_block *sb) | 225 | static int show_on_disk_super(struct seq_file *m, void *unused) |
222 | { | 226 | { |
227 | struct super_block *sb = m->private; | ||
223 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); | 228 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); |
224 | struct reiserfs_super_block *rs = sb_info->s_rs; | 229 | struct reiserfs_super_block *rs = sb_info->s_rs; |
225 | int hash_code = DFL(s_hash_function_code); | 230 | int hash_code = DFL(s_hash_function_code); |
@@ -261,8 +266,9 @@ static int show_on_disk_super(struct seq_file *m, struct super_block *sb) | |||
261 | return 0; | 266 | return 0; |
262 | } | 267 | } |
263 | 268 | ||
264 | static int show_oidmap(struct seq_file *m, struct super_block *sb) | 269 | static int show_oidmap(struct seq_file *m, void *unused) |
265 | { | 270 | { |
271 | struct super_block *sb = m->private; | ||
266 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); | 272 | struct reiserfs_sb_info *sb_info = REISERFS_SB(sb); |
267 | struct reiserfs_super_block *rs = sb_info->s_rs; | 273 | struct reiserfs_super_block *rs = sb_info->s_rs; |
268 | unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize); | 274 | unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize); |
@@ -291,8 +297,9 @@ static int show_oidmap(struct seq_file *m, struct super_block *sb) | |||
291 | return 0; | 297 | return 0; |
292 | } | 298 | } |
293 | 299 | ||
294 | static int show_journal(struct seq_file *m, struct super_block *sb) | 300 | static int show_journal(struct seq_file *m, void *unused) |
295 | { | 301 | { |
302 | struct super_block *sb = m->private; | ||
296 | struct reiserfs_sb_info *r = REISERFS_SB(sb); | 303 | struct reiserfs_sb_info *r = REISERFS_SB(sb); |
297 | struct reiserfs_super_block *rs = r->s_rs; | 304 | struct reiserfs_super_block *rs = r->s_rs; |
298 | struct journal_params *jp = &rs->s_v1.s_journal; | 305 | struct journal_params *jp = &rs->s_v1.s_journal; |
@@ -383,92 +390,24 @@ static int show_journal(struct seq_file *m, struct super_block *sb) | |||
383 | return 0; | 390 | return 0; |
384 | } | 391 | } |
385 | 392 | ||
386 | /* iterator */ | ||
387 | static int test_sb(struct super_block *sb, void *data) | ||
388 | { | ||
389 | return data == sb; | ||
390 | } | ||
391 | |||
392 | static int set_sb(struct super_block *sb, void *data) | ||
393 | { | ||
394 | return -ENOENT; | ||
395 | } | ||
396 | |||
397 | struct reiserfs_seq_private { | ||
398 | struct super_block *sb; | ||
399 | int (*show) (struct seq_file *, struct super_block *); | ||
400 | }; | ||
401 | |||
402 | static void *r_start(struct seq_file *m, loff_t * pos) | ||
403 | { | ||
404 | struct reiserfs_seq_private *priv = m->private; | ||
405 | loff_t l = *pos; | ||
406 | |||
407 | if (l) | ||
408 | return NULL; | ||
409 | |||
410 | if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, priv->sb))) | ||
411 | return NULL; | ||
412 | |||
413 | up_write(&priv->sb->s_umount); | ||
414 | return priv->sb; | ||
415 | } | ||
416 | |||
417 | static void *r_next(struct seq_file *m, void *v, loff_t * pos) | ||
418 | { | ||
419 | ++*pos; | ||
420 | if (v) | ||
421 | deactivate_super(v); | ||
422 | return NULL; | ||
423 | } | ||
424 | |||
425 | static void r_stop(struct seq_file *m, void *v) | ||
426 | { | ||
427 | if (v) | ||
428 | deactivate_super(v); | ||
429 | } | ||
430 | |||
431 | static int r_show(struct seq_file *m, void *v) | ||
432 | { | ||
433 | struct reiserfs_seq_private *priv = m->private; | ||
434 | return priv->show(m, v); | ||
435 | } | ||
436 | |||
437 | static const struct seq_operations r_ops = { | ||
438 | .start = r_start, | ||
439 | .next = r_next, | ||
440 | .stop = r_stop, | ||
441 | .show = r_show, | ||
442 | }; | ||
443 | |||
444 | static int r_open(struct inode *inode, struct file *file) | 393 | static int r_open(struct inode *inode, struct file *file) |
445 | { | 394 | { |
446 | struct reiserfs_seq_private *priv; | 395 | return single_open(file, PDE_DATA(inode), |
447 | int ret = seq_open_private(file, &r_ops, | 396 | proc_get_parent_data(inode)); |
448 | sizeof(struct reiserfs_seq_private)); | ||
449 | |||
450 | if (!ret) { | ||
451 | struct seq_file *m = file->private_data; | ||
452 | priv = m->private; | ||
453 | priv->sb = proc_get_parent_data(inode); | ||
454 | priv->show = PDE_DATA(inode); | ||
455 | } | ||
456 | return ret; | ||
457 | } | 397 | } |
458 | 398 | ||
459 | static const struct file_operations r_file_operations = { | 399 | static const struct file_operations r_file_operations = { |
460 | .open = r_open, | 400 | .open = r_open, |
461 | .read = seq_read, | 401 | .read = seq_read, |
462 | .llseek = seq_lseek, | 402 | .llseek = seq_lseek, |
463 | .release = seq_release_private, | 403 | .release = single_release, |
464 | .owner = THIS_MODULE, | ||
465 | }; | 404 | }; |
466 | 405 | ||
467 | static struct proc_dir_entry *proc_info_root = NULL; | 406 | static struct proc_dir_entry *proc_info_root = NULL; |
468 | static const char proc_info_root_name[] = "fs/reiserfs"; | 407 | static const char proc_info_root_name[] = "fs/reiserfs"; |
469 | 408 | ||
470 | static void add_file(struct super_block *sb, char *name, | 409 | static void add_file(struct super_block *sb, char *name, |
471 | int (*func) (struct seq_file *, struct super_block *)) | 410 | int (*func) (struct seq_file *, void *)) |
472 | { | 411 | { |
473 | proc_create_data(name, 0, REISERFS_SB(sb)->procdir, | 412 | proc_create_data(name, 0, REISERFS_SB(sb)->procdir, |
474 | &r_file_operations, func); | 413 | &r_file_operations, func); |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index f8a23c3078f8..e2e202a07b31 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -499,6 +499,7 @@ int remove_save_link(struct inode *inode, int truncate) | |||
499 | static void reiserfs_kill_sb(struct super_block *s) | 499 | static void reiserfs_kill_sb(struct super_block *s) |
500 | { | 500 | { |
501 | if (REISERFS_SB(s)) { | 501 | if (REISERFS_SB(s)) { |
502 | reiserfs_proc_info_done(s); | ||
502 | /* | 503 | /* |
503 | * Force any pending inode evictions to occur now. Any | 504 | * Force any pending inode evictions to occur now. Any |
504 | * inodes to be removed that have extended attributes | 505 | * inodes to be removed that have extended attributes |
@@ -554,8 +555,6 @@ static void reiserfs_put_super(struct super_block *s) | |||
554 | REISERFS_SB(s)->reserved_blocks); | 555 | REISERFS_SB(s)->reserved_blocks); |
555 | } | 556 | } |
556 | 557 | ||
557 | reiserfs_proc_info_done(s); | ||
558 | |||
559 | reiserfs_write_unlock(s); | 558 | reiserfs_write_unlock(s); |
560 | mutex_destroy(&REISERFS_SB(s)->lock); | 559 | mutex_destroy(&REISERFS_SB(s)->lock); |
561 | kfree(s->s_fs_info); | 560 | kfree(s->s_fs_info); |