diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-21 10:56:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-21 10:56:17 -0400 |
commit | 9a41fe3415bbef2c0c08ac232dc3a17add0dee58 (patch) | |
tree | 6c2440e3dd3babd4643396de9ba44303d8d3a7b4 | |
parent | 8b9cf76d0fa6cd98fe42dd2f86460d6ede55fed8 (diff) | |
parent | be9208dff23af904655807672dd8235abf6ac039 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
reiserfs: fix j_last_flush_trans_id type
fs: Mark get_filesystem_list() as __init function.
kill vfs_stat_fd / vfs_lstat_fd
Separate out common fstatat code into vfs_fstatat
ecryptfs: use memdup_user()
ncpfs: use memdup_user()
xfs: use memdup_user()
sysfs: use memdup_user()
btrfs: use memdup_user()
xattr: use memdup_user()
autofs4: use memchr() in invalid_string()
Documentation/filesystems: remove out of date reference to BKL being held
Fix i_mutex vs. readdir handling in nfsd
fs/compat_ioctl: fix build when !BLOCK
Fix autofs_expire()
No need for crossing to mountpoint in audit_tag_tree()
Safer nfsd_cross_mnt()
Touch all affected namespaces on propagation of mount
Fix AUTOFS_DEV_IOCTL_REQUESTER_CMD
-rw-r--r-- | Documentation/filesystems/vfs.txt | 3 | ||||
-rw-r--r-- | arch/arm/kernel/sys_oabi-compat.c | 19 | ||||
-rw-r--r-- | arch/s390/kernel/compat_linux.c | 18 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc32.c | 19 | ||||
-rw-r--r-- | arch/x86/ia32/sys_ia32.c | 19 | ||||
-rw-r--r-- | fs/autofs/dirhash.c | 34 | ||||
-rw-r--r-- | fs/autofs4/dev-ioctl.c | 12 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 49 | ||||
-rw-r--r-- | fs/btrfs/super.c | 13 | ||||
-rw-r--r-- | fs/compat.c | 37 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 7 | ||||
-rw-r--r-- | fs/dcache.c | 1 | ||||
-rw-r--r-- | fs/ecryptfs/miscdev.c | 15 | ||||
-rw-r--r-- | fs/filesystems.c | 2 | ||||
-rw-r--r-- | fs/namei.c | 2 | ||||
-rw-r--r-- | fs/namespace.c | 2 | ||||
-rw-r--r-- | fs/ncpfs/ioctl.c | 21 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 46 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 34 | ||||
-rw-r--r-- | fs/stat.c | 137 | ||||
-rw-r--r-- | fs/sysfs/bin.c | 13 | ||||
-rw-r--r-- | fs/xattr.c | 10 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 23 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 12 | ||||
-rw-r--r-- | include/linux/fs.h | 5 | ||||
-rw-r--r-- | include/linux/reiserfs_fs_sb.h | 2 | ||||
-rw-r--r-- | kernel/audit_tree.c | 3 |
27 files changed, 207 insertions, 351 deletions
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index deeeed0faa8f..f49eecf2e573 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -277,8 +277,7 @@ or bottom half). | |||
277 | unfreeze_fs: called when VFS is unlocking a filesystem and making it writable | 277 | unfreeze_fs: called when VFS is unlocking a filesystem and making it writable |
278 | again. | 278 | again. |
279 | 279 | ||
280 | statfs: called when the VFS needs to get filesystem statistics. This | 280 | statfs: called when the VFS needs to get filesystem statistics. |
281 | is called with the kernel lock held | ||
282 | 281 | ||
283 | remount_fs: called when the filesystem is remounted. This is called | 282 | remount_fs: called when the filesystem is remounted. This is called |
284 | with the kernel lock held | 283 | with the kernel lock held |
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c index e04173c7e621..d59a0cd537f0 100644 --- a/arch/arm/kernel/sys_oabi-compat.c +++ b/arch/arm/kernel/sys_oabi-compat.c | |||
@@ -177,21 +177,12 @@ asmlinkage long sys_oabi_fstatat64(int dfd, | |||
177 | int flag) | 177 | int flag) |
178 | { | 178 | { |
179 | struct kstat stat; | 179 | struct kstat stat; |
180 | int error = -EINVAL; | 180 | int error; |
181 | 181 | ||
182 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | 182 | error = vfs_fstatat(dfd, filename, &stat, flag); |
183 | goto out; | 183 | if (error) |
184 | 184 | return error; | |
185 | if (flag & AT_SYMLINK_NOFOLLOW) | 185 | return cp_oldabi_stat64(&stat, statbuf); |
186 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
187 | else | ||
188 | error = vfs_stat_fd(dfd, filename, &stat); | ||
189 | |||
190 | if (!error) | ||
191 | error = cp_oldabi_stat64(&stat, statbuf); | ||
192 | |||
193 | out: | ||
194 | return error; | ||
195 | } | 186 | } |
196 | 187 | ||
197 | struct oabi_flock64 { | 188 | struct oabi_flock64 { |
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 6cc87d8c8682..002c70d3cb75 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
@@ -702,20 +702,12 @@ asmlinkage long sys32_fstatat64(unsigned int dfd, char __user *filename, | |||
702 | struct stat64_emu31 __user* statbuf, int flag) | 702 | struct stat64_emu31 __user* statbuf, int flag) |
703 | { | 703 | { |
704 | struct kstat stat; | 704 | struct kstat stat; |
705 | int error = -EINVAL; | 705 | int error; |
706 | |||
707 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | ||
708 | goto out; | ||
709 | |||
710 | if (flag & AT_SYMLINK_NOFOLLOW) | ||
711 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
712 | else | ||
713 | error = vfs_stat_fd(dfd, filename, &stat); | ||
714 | 706 | ||
715 | if (!error) | 707 | error = vfs_fstatat(dfd, filename, &stat, flag); |
716 | error = cp_stat64(statbuf, &stat); | 708 | if (error) |
717 | out: | 709 | return error; |
718 | return error; | 710 | return cp_stat64(statbuf, &stat); |
719 | } | 711 | } |
720 | 712 | ||
721 | /* | 713 | /* |
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index e800503879e4..f5000a460c05 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c | |||
@@ -206,21 +206,12 @@ asmlinkage long compat_sys_fstatat64(unsigned int dfd, char __user *filename, | |||
206 | struct compat_stat64 __user * statbuf, int flag) | 206 | struct compat_stat64 __user * statbuf, int flag) |
207 | { | 207 | { |
208 | struct kstat stat; | 208 | struct kstat stat; |
209 | int error = -EINVAL; | 209 | int error; |
210 | |||
211 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | ||
212 | goto out; | ||
213 | |||
214 | if (flag & AT_SYMLINK_NOFOLLOW) | ||
215 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
216 | else | ||
217 | error = vfs_stat_fd(dfd, filename, &stat); | ||
218 | |||
219 | if (!error) | ||
220 | error = cp_compat_stat64(&stat, statbuf); | ||
221 | 210 | ||
222 | out: | 211 | error = vfs_fstatat(dfd, filename, &stat, flag); |
223 | return error; | 212 | if (error) |
213 | return error; | ||
214 | return cp_compat_stat64(&stat, statbuf); | ||
224 | } | 215 | } |
225 | 216 | ||
226 | asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2) | 217 | asmlinkage long compat_sys_sysfs(int option, u32 arg1, u32 arg2) |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index efac92fd1efb..085a8c35f149 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -129,21 +129,12 @@ asmlinkage long sys32_fstatat(unsigned int dfd, char __user *filename, | |||
129 | struct stat64 __user *statbuf, int flag) | 129 | struct stat64 __user *statbuf, int flag) |
130 | { | 130 | { |
131 | struct kstat stat; | 131 | struct kstat stat; |
132 | int error = -EINVAL; | 132 | int error; |
133 | 133 | ||
134 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | 134 | error = vfs_fstatat(dfd, filename, &stat, flag); |
135 | goto out; | 135 | if (error) |
136 | 136 | return error; | |
137 | if (flag & AT_SYMLINK_NOFOLLOW) | 137 | return cp_stat64(statbuf, &stat); |
138 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
139 | else | ||
140 | error = vfs_stat_fd(dfd, filename, &stat); | ||
141 | |||
142 | if (!error) | ||
143 | error = cp_stat64(statbuf, &stat); | ||
144 | |||
145 | out: | ||
146 | return error; | ||
147 | } | 138 | } |
148 | 139 | ||
149 | /* | 140 | /* |
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c index bf8c8af98004..4eb4d8dfb2f1 100644 --- a/fs/autofs/dirhash.c +++ b/fs/autofs/dirhash.c | |||
@@ -39,10 +39,12 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb, | |||
39 | { | 39 | { |
40 | struct autofs_dirhash *dh = &sbi->dirhash; | 40 | struct autofs_dirhash *dh = &sbi->dirhash; |
41 | struct autofs_dir_ent *ent; | 41 | struct autofs_dir_ent *ent; |
42 | struct dentry *dentry; | ||
43 | unsigned long timeout = sbi->exp_timeout; | 42 | unsigned long timeout = sbi->exp_timeout; |
44 | 43 | ||
45 | while (1) { | 44 | while (1) { |
45 | struct path path; | ||
46 | int umount_ok; | ||
47 | |||
46 | if ( list_empty(&dh->expiry_head) || sbi->catatonic ) | 48 | if ( list_empty(&dh->expiry_head) || sbi->catatonic ) |
47 | return NULL; /* No entries */ | 49 | return NULL; /* No entries */ |
48 | /* We keep the list sorted by last_usage and want old stuff */ | 50 | /* We keep the list sorted by last_usage and want old stuff */ |
@@ -57,17 +59,17 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb, | |||
57 | return ent; /* Symlinks are always expirable */ | 59 | return ent; /* Symlinks are always expirable */ |
58 | 60 | ||
59 | /* Get the dentry for the autofs subdirectory */ | 61 | /* Get the dentry for the autofs subdirectory */ |
60 | dentry = ent->dentry; | 62 | path.dentry = ent->dentry; |
61 | 63 | ||
62 | if ( !dentry ) { | 64 | if (!path.dentry) { |
63 | /* Should only happen in catatonic mode */ | 65 | /* Should only happen in catatonic mode */ |
64 | printk("autofs: dentry == NULL but inode range is directory, entry %s\n", ent->name); | 66 | printk("autofs: dentry == NULL but inode range is directory, entry %s\n", ent->name); |
65 | autofs_delete_usage(ent); | 67 | autofs_delete_usage(ent); |
66 | continue; | 68 | continue; |
67 | } | 69 | } |
68 | 70 | ||
69 | if ( !dentry->d_inode ) { | 71 | if (!path.dentry->d_inode) { |
70 | dput(dentry); | 72 | dput(path.dentry); |
71 | printk("autofs: negative dentry on expiry queue: %s\n", | 73 | printk("autofs: negative dentry on expiry queue: %s\n", |
72 | ent->name); | 74 | ent->name); |
73 | autofs_delete_usage(ent); | 75 | autofs_delete_usage(ent); |
@@ -76,29 +78,29 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb, | |||
76 | 78 | ||
77 | /* Make sure entry is mounted and unused; note that dentry will | 79 | /* Make sure entry is mounted and unused; note that dentry will |
78 | point to the mounted-on-top root. */ | 80 | point to the mounted-on-top root. */ |
79 | if (!S_ISDIR(dentry->d_inode->i_mode)||!d_mountpoint(dentry)) { | 81 | if (!S_ISDIR(path.dentry->d_inode->i_mode) || |
82 | !d_mountpoint(path.dentry)) { | ||
80 | DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name)); | 83 | DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name)); |
81 | continue; | 84 | continue; |
82 | } | 85 | } |
83 | mntget(mnt); | 86 | path.mnt = mnt; |
84 | dget(dentry); | 87 | path_get(&path); |
85 | if (!follow_down(&mnt, &dentry)) { | 88 | if (!follow_down(&path.mnt, &path.dentry)) { |
86 | dput(dentry); | 89 | path_put(&path); |
87 | mntput(mnt); | ||
88 | DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name)); | 90 | DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name)); |
89 | continue; | 91 | continue; |
90 | } | 92 | } |
91 | while (d_mountpoint(dentry) && follow_down(&mnt, &dentry)) | 93 | while (d_mountpoint(path.dentry) && |
94 | follow_down(&path.mnt, &path.dentry)) | ||
92 | ; | 95 | ; |
93 | dput(dentry); | 96 | umount_ok = may_umount(path.mnt); |
97 | path_put(&path); | ||
94 | 98 | ||
95 | if ( may_umount(mnt) ) { | 99 | if (umount_ok) { |
96 | mntput(mnt); | ||
97 | DPRINTK(("autofs: signaling expire on %s\n", ent->name)); | 100 | DPRINTK(("autofs: signaling expire on %s\n", ent->name)); |
98 | return ent; /* Expirable! */ | 101 | return ent; /* Expirable! */ |
99 | } | 102 | } |
100 | DPRINTK(("autofs: didn't expire due to may_umount: %s\n", ent->name)); | 103 | DPRINTK(("autofs: didn't expire due to may_umount: %s\n", ent->name)); |
101 | mntput(mnt); | ||
102 | } | 104 | } |
103 | return NULL; /* No expirable entries */ | 105 | return NULL; /* No expirable entries */ |
104 | } | 106 | } |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 9e5ae8a4f5c8..84168c0dcc2d 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -54,11 +54,10 @@ static int check_name(const char *name) | |||
54 | * Check a string doesn't overrun the chunk of | 54 | * Check a string doesn't overrun the chunk of |
55 | * memory we copied from user land. | 55 | * memory we copied from user land. |
56 | */ | 56 | */ |
57 | static int invalid_str(char *str, void *end) | 57 | static int invalid_str(char *str, size_t size) |
58 | { | 58 | { |
59 | while ((void *) str <= end) | 59 | if (memchr(str, 0, size)) |
60 | if (!*str++) | 60 | return 0; |
61 | return 0; | ||
62 | return -EINVAL; | 61 | return -EINVAL; |
63 | } | 62 | } |
64 | 63 | ||
@@ -138,8 +137,7 @@ static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) | |||
138 | } | 137 | } |
139 | 138 | ||
140 | if (param->size > sizeof(*param)) { | 139 | if (param->size > sizeof(*param)) { |
141 | err = invalid_str(param->path, | 140 | err = invalid_str(param->path, param->size - sizeof(*param)); |
142 | (void *) ((size_t) param + param->size)); | ||
143 | if (err) { | 141 | if (err) { |
144 | AUTOFS_WARN( | 142 | AUTOFS_WARN( |
145 | "path string terminator missing for cmd(0x%08x)", | 143 | "path string terminator missing for cmd(0x%08x)", |
@@ -488,7 +486,7 @@ static int autofs_dev_ioctl_requester(struct file *fp, | |||
488 | } | 486 | } |
489 | 487 | ||
490 | path = param->path; | 488 | path = param->path; |
491 | devid = sbi->sb->s_dev; | 489 | devid = new_encode_dev(sbi->sb->s_dev); |
492 | 490 | ||
493 | param->requester.uid = param->requester.gid = -1; | 491 | param->requester.uid = param->requester.gid = -1; |
494 | 492 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 7594bec1be10..9f135e878507 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -461,15 +461,9 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
461 | if (!capable(CAP_SYS_ADMIN)) | 461 | if (!capable(CAP_SYS_ADMIN)) |
462 | return -EPERM; | 462 | return -EPERM; |
463 | 463 | ||
464 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 464 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
465 | 465 | if (IS_ERR(vol_args)) | |
466 | if (!vol_args) | 466 | return PTR_ERR(vol_args); |
467 | return -ENOMEM; | ||
468 | |||
469 | if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { | ||
470 | ret = -EFAULT; | ||
471 | goto out; | ||
472 | } | ||
473 | 467 | ||
474 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 468 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
475 | namelen = strlen(vol_args->name); | 469 | namelen = strlen(vol_args->name); |
@@ -545,7 +539,6 @@ static int btrfs_ioctl_resize(struct btrfs_root *root, void __user *arg) | |||
545 | 539 | ||
546 | out_unlock: | 540 | out_unlock: |
547 | mutex_unlock(&root->fs_info->volume_mutex); | 541 | mutex_unlock(&root->fs_info->volume_mutex); |
548 | out: | ||
549 | kfree(vol_args); | 542 | kfree(vol_args); |
550 | return ret; | 543 | return ret; |
551 | } | 544 | } |
@@ -565,15 +558,9 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
565 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 558 | if (root->fs_info->sb->s_flags & MS_RDONLY) |
566 | return -EROFS; | 559 | return -EROFS; |
567 | 560 | ||
568 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 561 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
569 | 562 | if (IS_ERR(vol_args)) | |
570 | if (!vol_args) | 563 | return PTR_ERR(vol_args); |
571 | return -ENOMEM; | ||
572 | |||
573 | if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { | ||
574 | ret = -EFAULT; | ||
575 | goto out; | ||
576 | } | ||
577 | 564 | ||
578 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 565 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
579 | namelen = strlen(vol_args->name); | 566 | namelen = strlen(vol_args->name); |
@@ -675,19 +662,13 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | |||
675 | if (!capable(CAP_SYS_ADMIN)) | 662 | if (!capable(CAP_SYS_ADMIN)) |
676 | return -EPERM; | 663 | return -EPERM; |
677 | 664 | ||
678 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 665 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
666 | if (IS_ERR(vol_args)) | ||
667 | return PTR_ERR(vol_args); | ||
679 | 668 | ||
680 | if (!vol_args) | ||
681 | return -ENOMEM; | ||
682 | |||
683 | if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { | ||
684 | ret = -EFAULT; | ||
685 | goto out; | ||
686 | } | ||
687 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 669 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
688 | ret = btrfs_init_new_device(root, vol_args->name); | 670 | ret = btrfs_init_new_device(root, vol_args->name); |
689 | 671 | ||
690 | out: | ||
691 | kfree(vol_args); | 672 | kfree(vol_args); |
692 | return ret; | 673 | return ret; |
693 | } | 674 | } |
@@ -703,19 +684,13 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | |||
703 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 684 | if (root->fs_info->sb->s_flags & MS_RDONLY) |
704 | return -EROFS; | 685 | return -EROFS; |
705 | 686 | ||
706 | vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); | 687 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
688 | if (IS_ERR(vol_args)) | ||
689 | return PTR_ERR(vol_args); | ||
707 | 690 | ||
708 | if (!vol_args) | ||
709 | return -ENOMEM; | ||
710 | |||
711 | if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { | ||
712 | ret = -EFAULT; | ||
713 | goto out; | ||
714 | } | ||
715 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 691 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
716 | ret = btrfs_rm_device(root, vol_args->name); | 692 | ret = btrfs_rm_device(root, vol_args->name); |
717 | 693 | ||
718 | out: | ||
719 | kfree(vol_args); | 694 | kfree(vol_args); |
720 | return ret; | 695 | return ret; |
721 | } | 696 | } |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 9744af9d71e9..a7acfe639a44 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -635,14 +635,9 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, | |||
635 | if (!capable(CAP_SYS_ADMIN)) | 635 | if (!capable(CAP_SYS_ADMIN)) |
636 | return -EPERM; | 636 | return -EPERM; |
637 | 637 | ||
638 | vol = kmalloc(sizeof(*vol), GFP_KERNEL); | 638 | vol = memdup_user((void __user *)arg, sizeof(*vol)); |
639 | if (!vol) | 639 | if (IS_ERR(vol)) |
640 | return -ENOMEM; | 640 | return PTR_ERR(vol); |
641 | |||
642 | if (copy_from_user(vol, (void __user *)arg, sizeof(*vol))) { | ||
643 | ret = -EFAULT; | ||
644 | goto out; | ||
645 | } | ||
646 | 641 | ||
647 | switch (cmd) { | 642 | switch (cmd) { |
648 | case BTRFS_IOC_SCAN_DEV: | 643 | case BTRFS_IOC_SCAN_DEV: |
@@ -650,7 +645,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, | |||
650 | &btrfs_fs_type, &fs_devices); | 645 | &btrfs_fs_type, &fs_devices); |
651 | break; | 646 | break; |
652 | } | 647 | } |
653 | out: | 648 | |
654 | kfree(vol); | 649 | kfree(vol); |
655 | return ret; | 650 | return ret; |
656 | } | 651 | } |
diff --git a/fs/compat.c b/fs/compat.c index 3f84d5f15889..379a399bf5c3 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -181,22 +181,24 @@ asmlinkage long compat_sys_newstat(char __user * filename, | |||
181 | struct compat_stat __user *statbuf) | 181 | struct compat_stat __user *statbuf) |
182 | { | 182 | { |
183 | struct kstat stat; | 183 | struct kstat stat; |
184 | int error = vfs_stat_fd(AT_FDCWD, filename, &stat); | 184 | int error; |
185 | 185 | ||
186 | if (!error) | 186 | error = vfs_stat(filename, &stat); |
187 | error = cp_compat_stat(&stat, statbuf); | 187 | if (error) |
188 | return error; | 188 | return error; |
189 | return cp_compat_stat(&stat, statbuf); | ||
189 | } | 190 | } |
190 | 191 | ||
191 | asmlinkage long compat_sys_newlstat(char __user * filename, | 192 | asmlinkage long compat_sys_newlstat(char __user * filename, |
192 | struct compat_stat __user *statbuf) | 193 | struct compat_stat __user *statbuf) |
193 | { | 194 | { |
194 | struct kstat stat; | 195 | struct kstat stat; |
195 | int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); | 196 | int error; |
196 | 197 | ||
197 | if (!error) | 198 | error = vfs_lstat(filename, &stat); |
198 | error = cp_compat_stat(&stat, statbuf); | 199 | if (error) |
199 | return error; | 200 | return error; |
201 | return cp_compat_stat(&stat, statbuf); | ||
200 | } | 202 | } |
201 | 203 | ||
202 | #ifndef __ARCH_WANT_STAT64 | 204 | #ifndef __ARCH_WANT_STAT64 |
@@ -204,21 +206,12 @@ asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename, | |||
204 | struct compat_stat __user *statbuf, int flag) | 206 | struct compat_stat __user *statbuf, int flag) |
205 | { | 207 | { |
206 | struct kstat stat; | 208 | struct kstat stat; |
207 | int error = -EINVAL; | 209 | int error; |
208 | |||
209 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | ||
210 | goto out; | ||
211 | |||
212 | if (flag & AT_SYMLINK_NOFOLLOW) | ||
213 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
214 | else | ||
215 | error = vfs_stat_fd(dfd, filename, &stat); | ||
216 | |||
217 | if (!error) | ||
218 | error = cp_compat_stat(&stat, statbuf); | ||
219 | 210 | ||
220 | out: | 211 | error = vfs_fstatat(dfd, filename, &stat, flag); |
221 | return error; | 212 | if (error) |
213 | return error; | ||
214 | return cp_compat_stat(&stat, statbuf); | ||
222 | } | 215 | } |
223 | #endif | 216 | #endif |
224 | 217 | ||
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 3e87ce443ea2..b83f6bcfa51a 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -58,7 +58,6 @@ | |||
58 | #include <linux/i2c.h> | 58 | #include <linux/i2c.h> |
59 | #include <linux/i2c-dev.h> | 59 | #include <linux/i2c-dev.h> |
60 | #include <linux/atalk.h> | 60 | #include <linux/atalk.h> |
61 | #include <linux/loop.h> | ||
62 | 61 | ||
63 | #include <net/bluetooth/bluetooth.h> | 62 | #include <net/bluetooth/bluetooth.h> |
64 | #include <net/bluetooth/hci.h> | 63 | #include <net/bluetooth/hci.h> |
@@ -68,6 +67,7 @@ | |||
68 | #include <linux/gigaset_dev.h> | 67 | #include <linux/gigaset_dev.h> |
69 | 68 | ||
70 | #ifdef CONFIG_BLOCK | 69 | #ifdef CONFIG_BLOCK |
70 | #include <linux/loop.h> | ||
71 | #include <scsi/scsi.h> | 71 | #include <scsi/scsi.h> |
72 | #include <scsi/scsi_ioctl.h> | 72 | #include <scsi/scsi_ioctl.h> |
73 | #include <scsi/sg.h> | 73 | #include <scsi/sg.h> |
@@ -2660,6 +2660,8 @@ HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) | |||
2660 | HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) | 2660 | HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) |
2661 | /* block stuff */ | 2661 | /* block stuff */ |
2662 | #ifdef CONFIG_BLOCK | 2662 | #ifdef CONFIG_BLOCK |
2663 | /* loop */ | ||
2664 | IGNORE_IOCTL(LOOP_CLR_FD) | ||
2663 | /* Raw devices */ | 2665 | /* Raw devices */ |
2664 | HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) | 2666 | HANDLE_IOCTL(RAW_SETBIND, raw_ioctl) |
2665 | HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) | 2667 | HANDLE_IOCTL(RAW_GETBIND, raw_ioctl) |
@@ -2728,9 +2730,6 @@ HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans) | |||
2728 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32) | 2730 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32) |
2729 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32) | 2731 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32) |
2730 | 2732 | ||
2731 | /* loop */ | ||
2732 | IGNORE_IOCTL(LOOP_CLR_FD) | ||
2733 | |||
2734 | #ifdef CONFIG_SPARC | 2733 | #ifdef CONFIG_SPARC |
2735 | /* Sparc framebuffers, handled in sbusfb_compat_ioctl() */ | 2734 | /* Sparc framebuffers, handled in sbusfb_compat_ioctl() */ |
2736 | IGNORE_IOCTL(FBIOGTYPE) | 2735 | IGNORE_IOCTL(FBIOGTYPE) |
diff --git a/fs/dcache.c b/fs/dcache.c index 761d30be2683..1fcffebfb44f 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -2149,7 +2149,6 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry) | |||
2149 | int result; | 2149 | int result; |
2150 | unsigned long seq; | 2150 | unsigned long seq; |
2151 | 2151 | ||
2152 | /* FIXME: This is old behavior, needed? Please check callers. */ | ||
2153 | if (new_dentry == old_dentry) | 2152 | if (new_dentry == old_dentry) |
2154 | return 1; | 2153 | return 1; |
2155 | 2154 | ||
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index a67fea655f49..dda3c58eefc0 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c | |||
@@ -418,18 +418,13 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, | |||
418 | 418 | ||
419 | if (count == 0) | 419 | if (count == 0) |
420 | goto out; | 420 | goto out; |
421 | data = kmalloc(count, GFP_KERNEL); | 421 | |
422 | if (!data) { | 422 | data = memdup_user(buf, count); |
423 | printk(KERN_ERR "%s: Out of memory whilst attempting to " | 423 | if (IS_ERR(data)) { |
424 | "kmalloc([%zd], GFP_KERNEL)\n", __func__, count); | 424 | printk(KERN_ERR "%s: memdup_user returned error [%ld]\n", |
425 | __func__, PTR_ERR(data)); | ||
425 | goto out; | 426 | goto out; |
426 | } | 427 | } |
427 | rc = copy_from_user(data, buf, count); | ||
428 | if (rc) { | ||
429 | printk(KERN_ERR "%s: copy_from_user returned error [%d]\n", | ||
430 | __func__, rc); | ||
431 | goto out_free; | ||
432 | } | ||
433 | sz = count; | 428 | sz = count; |
434 | i = 0; | 429 | i = 0; |
435 | switch (data[i++]) { | 430 | switch (data[i++]) { |
diff --git a/fs/filesystems.c b/fs/filesystems.c index 1aa70260e6d1..a24c58e181db 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c | |||
@@ -199,7 +199,7 @@ SYSCALL_DEFINE3(sysfs, int, option, unsigned long, arg1, unsigned long, arg2) | |||
199 | return retval; | 199 | return retval; |
200 | } | 200 | } |
201 | 201 | ||
202 | int get_filesystem_list(char * buf) | 202 | int __init get_filesystem_list(char *buf) |
203 | { | 203 | { |
204 | int len = 0; | 204 | int len = 0; |
205 | struct file_system_type * tmp; | 205 | struct file_system_type * tmp; |
diff --git a/fs/namei.c b/fs/namei.c index b8433ebfae05..78f253cd2d4f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1248,6 +1248,8 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | |||
1248 | int err; | 1248 | int err; |
1249 | struct qstr this; | 1249 | struct qstr this; |
1250 | 1250 | ||
1251 | WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex)); | ||
1252 | |||
1251 | err = __lookup_one_len(name, &this, base, len); | 1253 | err = __lookup_one_len(name, &this, base, len); |
1252 | if (err) | 1254 | if (err) |
1253 | return ERR_PTR(err); | 1255 | return ERR_PTR(err); |
diff --git a/fs/namespace.c b/fs/namespace.c index d9138f81ec10..41196209a906 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1377,7 +1377,7 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
1377 | if (parent_path) { | 1377 | if (parent_path) { |
1378 | detach_mnt(source_mnt, parent_path); | 1378 | detach_mnt(source_mnt, parent_path); |
1379 | attach_mnt(source_mnt, path); | 1379 | attach_mnt(source_mnt, path); |
1380 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 1380 | touch_mnt_namespace(parent_path->mnt->mnt_ns); |
1381 | } else { | 1381 | } else { |
1382 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); | 1382 | mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); |
1383 | commit_tree(source_mnt); | 1383 | commit_tree(source_mnt); |
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index f54360f50a9c..fa038df63ac8 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c | |||
@@ -660,13 +660,10 @@ outrel: | |||
660 | if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) | 660 | if (user.object_name_len > NCP_OBJECT_NAME_MAX_LEN) |
661 | return -ENOMEM; | 661 | return -ENOMEM; |
662 | if (user.object_name_len) { | 662 | if (user.object_name_len) { |
663 | newname = kmalloc(user.object_name_len, GFP_USER); | 663 | newname = memdup_user(user.object_name, |
664 | if (!newname) | 664 | user.object_name_len); |
665 | return -ENOMEM; | 665 | if (IS_ERR(newname)) |
666 | if (copy_from_user(newname, user.object_name, user.object_name_len)) { | 666 | return PTR_ERR(newname); |
667 | kfree(newname); | ||
668 | return -EFAULT; | ||
669 | } | ||
670 | } else { | 667 | } else { |
671 | newname = NULL; | 668 | newname = NULL; |
672 | } | 669 | } |
@@ -760,13 +757,9 @@ outrel: | |||
760 | if (user.len > NCP_PRIVATE_DATA_MAX_LEN) | 757 | if (user.len > NCP_PRIVATE_DATA_MAX_LEN) |
761 | return -ENOMEM; | 758 | return -ENOMEM; |
762 | if (user.len) { | 759 | if (user.len) { |
763 | new = kmalloc(user.len, GFP_USER); | 760 | new = memdup_user(user.data, user.len); |
764 | if (!new) | 761 | if (IS_ERR(new)) |
765 | return -ENOMEM; | 762 | return PTR_ERR(new); |
766 | if (copy_from_user(new, user.data, user.len)) { | ||
767 | kfree(new); | ||
768 | return -EFAULT; | ||
769 | } | ||
770 | } else { | 763 | } else { |
771 | new = NULL; | 764 | new = NULL; |
772 | } | 765 | } |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 3444c0052a87..5275097a7565 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -229,21 +229,23 @@ nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f) | |||
229 | goto out; | 229 | goto out; |
230 | status = vfs_readdir(filp, nfsd4_build_namelist, &names); | 230 | status = vfs_readdir(filp, nfsd4_build_namelist, &names); |
231 | fput(filp); | 231 | fput(filp); |
232 | mutex_lock(&dir->d_inode->i_mutex); | ||
232 | while (!list_empty(&names)) { | 233 | while (!list_empty(&names)) { |
233 | entry = list_entry(names.next, struct name_list, list); | 234 | entry = list_entry(names.next, struct name_list, list); |
234 | 235 | ||
235 | dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); | 236 | dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); |
236 | if (IS_ERR(dentry)) { | 237 | if (IS_ERR(dentry)) { |
237 | status = PTR_ERR(dentry); | 238 | status = PTR_ERR(dentry); |
238 | goto out; | 239 | break; |
239 | } | 240 | } |
240 | status = f(dir, dentry); | 241 | status = f(dir, dentry); |
241 | dput(dentry); | 242 | dput(dentry); |
242 | if (status) | 243 | if (status) |
243 | goto out; | 244 | break; |
244 | list_del(&entry->list); | 245 | list_del(&entry->list); |
245 | kfree(entry); | 246 | kfree(entry); |
246 | } | 247 | } |
248 | mutex_unlock(&dir->d_inode->i_mutex); | ||
247 | out: | 249 | out: |
248 | while (!list_empty(&names)) { | 250 | while (!list_empty(&names)) { |
249 | entry = list_entry(names.next, struct name_list, list); | 251 | entry = list_entry(names.next, struct name_list, list); |
@@ -255,36 +257,6 @@ out: | |||
255 | } | 257 | } |
256 | 258 | ||
257 | static int | 259 | static int |
258 | nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry) | ||
259 | { | ||
260 | int status; | ||
261 | |||
262 | if (!S_ISREG(dir->d_inode->i_mode)) { | ||
263 | printk("nfsd4: non-file found in client recovery directory\n"); | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | ||
267 | status = vfs_unlink(dir->d_inode, dentry); | ||
268 | mutex_unlock(&dir->d_inode->i_mutex); | ||
269 | return status; | ||
270 | } | ||
271 | |||
272 | static int | ||
273 | nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry) | ||
274 | { | ||
275 | int status; | ||
276 | |||
277 | /* For now this directory should already be empty, but we empty it of | ||
278 | * any regular files anyway, just in case the directory was created by | ||
279 | * a kernel from the future.... */ | ||
280 | nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file); | ||
281 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | ||
282 | status = vfs_rmdir(dir->d_inode, dentry); | ||
283 | mutex_unlock(&dir->d_inode->i_mutex); | ||
284 | return status; | ||
285 | } | ||
286 | |||
287 | static int | ||
288 | nfsd4_unlink_clid_dir(char *name, int namlen) | 260 | nfsd4_unlink_clid_dir(char *name, int namlen) |
289 | { | 261 | { |
290 | struct dentry *dentry; | 262 | struct dentry *dentry; |
@@ -294,18 +266,18 @@ nfsd4_unlink_clid_dir(char *name, int namlen) | |||
294 | 266 | ||
295 | mutex_lock(&rec_dir.dentry->d_inode->i_mutex); | 267 | mutex_lock(&rec_dir.dentry->d_inode->i_mutex); |
296 | dentry = lookup_one_len(name, rec_dir.dentry, namlen); | 268 | dentry = lookup_one_len(name, rec_dir.dentry, namlen); |
297 | mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); | ||
298 | if (IS_ERR(dentry)) { | 269 | if (IS_ERR(dentry)) { |
299 | status = PTR_ERR(dentry); | 270 | status = PTR_ERR(dentry); |
300 | return status; | 271 | goto out_unlock; |
301 | } | 272 | } |
302 | status = -ENOENT; | 273 | status = -ENOENT; |
303 | if (!dentry->d_inode) | 274 | if (!dentry->d_inode) |
304 | goto out; | 275 | goto out; |
305 | 276 | status = vfs_rmdir(rec_dir.dentry->d_inode, dentry); | |
306 | status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry); | ||
307 | out: | 277 | out: |
308 | dput(dentry); | 278 | dput(dentry); |
279 | out_unlock: | ||
280 | mutex_unlock(&rec_dir.dentry->d_inode->i_mutex); | ||
309 | return status; | 281 | return status; |
310 | } | 282 | } |
311 | 283 | ||
@@ -348,7 +320,7 @@ purge_old(struct dentry *parent, struct dentry *child) | |||
348 | if (nfs4_has_reclaimed_state(child->d_name.name, false)) | 320 | if (nfs4_has_reclaimed_state(child->d_name.name, false)) |
349 | return 0; | 321 | return 0; |
350 | 322 | ||
351 | status = nfsd4_clear_clid_dir(parent, child); | 323 | status = vfs_rmdir(parent->d_inode, child); |
352 | if (status) | 324 | if (status) |
353 | printk("failed to remove client recovery directory %s\n", | 325 | printk("failed to remove client recovery directory %s\n", |
354 | child->d_name.name); | 326 | child->d_name.name); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index ab93fcfef254..6c68ffd6b4bb 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -116,10 +116,15 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, | |||
116 | } | 116 | } |
117 | if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) { | 117 | if ((exp->ex_flags & NFSEXP_CROSSMOUNT) || EX_NOHIDE(exp2)) { |
118 | /* successfully crossed mount point */ | 118 | /* successfully crossed mount point */ |
119 | exp_put(exp); | 119 | /* |
120 | *expp = exp2; | 120 | * This is subtle: dentry is *not* under mnt at this point. |
121 | * The only reason we are safe is that original mnt is pinned | ||
122 | * down by exp, so we should dput before putting exp. | ||
123 | */ | ||
121 | dput(dentry); | 124 | dput(dentry); |
122 | *dpp = mounts; | 125 | *dpp = mounts; |
126 | exp_put(exp); | ||
127 | *expp = exp2; | ||
123 | } else { | 128 | } else { |
124 | exp_put(exp2); | 129 | exp_put(exp2); |
125 | dput(mounts); | 130 | dput(mounts); |
@@ -1885,8 +1890,8 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen, | |||
1885 | return 0; | 1890 | return 0; |
1886 | } | 1891 | } |
1887 | 1892 | ||
1888 | static int nfsd_buffered_readdir(struct file *file, filldir_t func, | 1893 | static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func, |
1889 | struct readdir_cd *cdp, loff_t *offsetp) | 1894 | struct readdir_cd *cdp, loff_t *offsetp) |
1890 | { | 1895 | { |
1891 | struct readdir_data buf; | 1896 | struct readdir_data buf; |
1892 | struct buffered_dirent *de; | 1897 | struct buffered_dirent *de; |
@@ -1896,11 +1901,12 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, | |||
1896 | 1901 | ||
1897 | buf.dirent = (void *)__get_free_page(GFP_KERNEL); | 1902 | buf.dirent = (void *)__get_free_page(GFP_KERNEL); |
1898 | if (!buf.dirent) | 1903 | if (!buf.dirent) |
1899 | return -ENOMEM; | 1904 | return nfserrno(-ENOMEM); |
1900 | 1905 | ||
1901 | offset = *offsetp; | 1906 | offset = *offsetp; |
1902 | 1907 | ||
1903 | while (1) { | 1908 | while (1) { |
1909 | struct inode *dir_inode = file->f_path.dentry->d_inode; | ||
1904 | unsigned int reclen; | 1910 | unsigned int reclen; |
1905 | 1911 | ||
1906 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | 1912 | cdp->err = nfserr_eof; /* will be cleared on successful read */ |
@@ -1919,26 +1925,38 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, | |||
1919 | if (!size) | 1925 | if (!size) |
1920 | break; | 1926 | break; |
1921 | 1927 | ||
1928 | /* | ||
1929 | * Various filldir functions may end up calling back into | ||
1930 | * lookup_one_len() and the file system's ->lookup() method. | ||
1931 | * These expect i_mutex to be held, as it would within readdir. | ||
1932 | */ | ||
1933 | host_err = mutex_lock_killable(&dir_inode->i_mutex); | ||
1934 | if (host_err) | ||
1935 | break; | ||
1936 | |||
1922 | de = (struct buffered_dirent *)buf.dirent; | 1937 | de = (struct buffered_dirent *)buf.dirent; |
1923 | while (size > 0) { | 1938 | while (size > 0) { |
1924 | offset = de->offset; | 1939 | offset = de->offset; |
1925 | 1940 | ||
1926 | if (func(cdp, de->name, de->namlen, de->offset, | 1941 | if (func(cdp, de->name, de->namlen, de->offset, |
1927 | de->ino, de->d_type)) | 1942 | de->ino, de->d_type)) |
1928 | goto done; | 1943 | break; |
1929 | 1944 | ||
1930 | if (cdp->err != nfs_ok) | 1945 | if (cdp->err != nfs_ok) |
1931 | goto done; | 1946 | break; |
1932 | 1947 | ||
1933 | reclen = ALIGN(sizeof(*de) + de->namlen, | 1948 | reclen = ALIGN(sizeof(*de) + de->namlen, |
1934 | sizeof(u64)); | 1949 | sizeof(u64)); |
1935 | size -= reclen; | 1950 | size -= reclen; |
1936 | de = (struct buffered_dirent *)((char *)de + reclen); | 1951 | de = (struct buffered_dirent *)((char *)de + reclen); |
1937 | } | 1952 | } |
1953 | mutex_unlock(&dir_inode->i_mutex); | ||
1954 | if (size > 0) /* We bailed out early */ | ||
1955 | break; | ||
1956 | |||
1938 | offset = vfs_llseek(file, 0, SEEK_CUR); | 1957 | offset = vfs_llseek(file, 0, SEEK_CUR); |
1939 | } | 1958 | } |
1940 | 1959 | ||
1941 | done: | ||
1942 | free_page((unsigned long)(buf.dirent)); | 1960 | free_page((unsigned long)(buf.dirent)); |
1943 | 1961 | ||
1944 | if (host_err) | 1962 | if (host_err) |
@@ -55,59 +55,54 @@ int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
55 | 55 | ||
56 | EXPORT_SYMBOL(vfs_getattr); | 56 | EXPORT_SYMBOL(vfs_getattr); |
57 | 57 | ||
58 | int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat) | 58 | int vfs_fstat(unsigned int fd, struct kstat *stat) |
59 | { | 59 | { |
60 | struct path path; | 60 | struct file *f = fget(fd); |
61 | int error; | 61 | int error = -EBADF; |
62 | 62 | ||
63 | error = user_path_at(dfd, name, LOOKUP_FOLLOW, &path); | 63 | if (f) { |
64 | if (!error) { | 64 | error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); |
65 | error = vfs_getattr(path.mnt, path.dentry, stat); | 65 | fput(f); |
66 | path_put(&path); | ||
67 | } | 66 | } |
68 | return error; | 67 | return error; |
69 | } | 68 | } |
69 | EXPORT_SYMBOL(vfs_fstat); | ||
70 | 70 | ||
71 | int vfs_stat(char __user *name, struct kstat *stat) | 71 | int vfs_fstatat(int dfd, char __user *filename, struct kstat *stat, int flag) |
72 | { | 72 | { |
73 | return vfs_stat_fd(AT_FDCWD, name, stat); | 73 | struct path path; |
74 | } | 74 | int error = -EINVAL; |
75 | int lookup_flags = 0; | ||
75 | 76 | ||
76 | EXPORT_SYMBOL(vfs_stat); | 77 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) |
78 | goto out; | ||
77 | 79 | ||
78 | int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) | 80 | if (!(flag & AT_SYMLINK_NOFOLLOW)) |
79 | { | 81 | lookup_flags |= LOOKUP_FOLLOW; |
80 | struct path path; | ||
81 | int error; | ||
82 | 82 | ||
83 | error = user_path_at(dfd, name, 0, &path); | 83 | error = user_path_at(dfd, filename, lookup_flags, &path); |
84 | if (!error) { | 84 | if (error) |
85 | error = vfs_getattr(path.mnt, path.dentry, stat); | 85 | goto out; |
86 | path_put(&path); | 86 | |
87 | } | 87 | error = vfs_getattr(path.mnt, path.dentry, stat); |
88 | path_put(&path); | ||
89 | out: | ||
88 | return error; | 90 | return error; |
89 | } | 91 | } |
92 | EXPORT_SYMBOL(vfs_fstatat); | ||
90 | 93 | ||
91 | int vfs_lstat(char __user *name, struct kstat *stat) | 94 | int vfs_stat(char __user *name, struct kstat *stat) |
92 | { | 95 | { |
93 | return vfs_lstat_fd(AT_FDCWD, name, stat); | 96 | return vfs_fstatat(AT_FDCWD, name, stat, 0); |
94 | } | 97 | } |
98 | EXPORT_SYMBOL(vfs_stat); | ||
95 | 99 | ||
96 | EXPORT_SYMBOL(vfs_lstat); | 100 | int vfs_lstat(char __user *name, struct kstat *stat) |
97 | |||
98 | int vfs_fstat(unsigned int fd, struct kstat *stat) | ||
99 | { | 101 | { |
100 | struct file *f = fget(fd); | 102 | return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW); |
101 | int error = -EBADF; | ||
102 | |||
103 | if (f) { | ||
104 | error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); | ||
105 | fput(f); | ||
106 | } | ||
107 | return error; | ||
108 | } | 103 | } |
104 | EXPORT_SYMBOL(vfs_lstat); | ||
109 | 105 | ||
110 | EXPORT_SYMBOL(vfs_fstat); | ||
111 | 106 | ||
112 | #ifdef __ARCH_WANT_OLD_STAT | 107 | #ifdef __ARCH_WANT_OLD_STAT |
113 | 108 | ||
@@ -155,23 +150,25 @@ static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * sta | |||
155 | SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf) | 150 | SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf) |
156 | { | 151 | { |
157 | struct kstat stat; | 152 | struct kstat stat; |
158 | int error = vfs_stat_fd(AT_FDCWD, filename, &stat); | 153 | int error; |
159 | 154 | ||
160 | if (!error) | 155 | error = vfs_stat(filename, &stat); |
161 | error = cp_old_stat(&stat, statbuf); | 156 | if (error) |
157 | return error; | ||
162 | 158 | ||
163 | return error; | 159 | return cp_old_stat(&stat, statbuf); |
164 | } | 160 | } |
165 | 161 | ||
166 | SYSCALL_DEFINE2(lstat, char __user *, filename, struct __old_kernel_stat __user *, statbuf) | 162 | SYSCALL_DEFINE2(lstat, char __user *, filename, struct __old_kernel_stat __user *, statbuf) |
167 | { | 163 | { |
168 | struct kstat stat; | 164 | struct kstat stat; |
169 | int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); | 165 | int error; |
170 | 166 | ||
171 | if (!error) | 167 | error = vfs_lstat(filename, &stat); |
172 | error = cp_old_stat(&stat, statbuf); | 168 | if (error) |
169 | return error; | ||
173 | 170 | ||
174 | return error; | 171 | return cp_old_stat(&stat, statbuf); |
175 | } | 172 | } |
176 | 173 | ||
177 | SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf) | 174 | SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf) |
@@ -240,23 +237,23 @@ static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf) | |||
240 | SYSCALL_DEFINE2(newstat, char __user *, filename, struct stat __user *, statbuf) | 237 | SYSCALL_DEFINE2(newstat, char __user *, filename, struct stat __user *, statbuf) |
241 | { | 238 | { |
242 | struct kstat stat; | 239 | struct kstat stat; |
243 | int error = vfs_stat_fd(AT_FDCWD, filename, &stat); | 240 | int error = vfs_stat(filename, &stat); |
244 | |||
245 | if (!error) | ||
246 | error = cp_new_stat(&stat, statbuf); | ||
247 | 241 | ||
248 | return error; | 242 | if (error) |
243 | return error; | ||
244 | return cp_new_stat(&stat, statbuf); | ||
249 | } | 245 | } |
250 | 246 | ||
251 | SYSCALL_DEFINE2(newlstat, char __user *, filename, struct stat __user *, statbuf) | 247 | SYSCALL_DEFINE2(newlstat, char __user *, filename, struct stat __user *, statbuf) |
252 | { | 248 | { |
253 | struct kstat stat; | 249 | struct kstat stat; |
254 | int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); | 250 | int error; |
255 | 251 | ||
256 | if (!error) | 252 | error = vfs_lstat(filename, &stat); |
257 | error = cp_new_stat(&stat, statbuf); | 253 | if (error) |
254 | return error; | ||
258 | 255 | ||
259 | return error; | 256 | return cp_new_stat(&stat, statbuf); |
260 | } | 257 | } |
261 | 258 | ||
262 | #if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT) | 259 | #if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT) |
@@ -264,21 +261,12 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, char __user *, filename, | |||
264 | struct stat __user *, statbuf, int, flag) | 261 | struct stat __user *, statbuf, int, flag) |
265 | { | 262 | { |
266 | struct kstat stat; | 263 | struct kstat stat; |
267 | int error = -EINVAL; | 264 | int error; |
268 | |||
269 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | ||
270 | goto out; | ||
271 | |||
272 | if (flag & AT_SYMLINK_NOFOLLOW) | ||
273 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
274 | else | ||
275 | error = vfs_stat_fd(dfd, filename, &stat); | ||
276 | |||
277 | if (!error) | ||
278 | error = cp_new_stat(&stat, statbuf); | ||
279 | 265 | ||
280 | out: | 266 | error = vfs_fstatat(dfd, filename, &stat, flag); |
281 | return error; | 267 | if (error) |
268 | return error; | ||
269 | return cp_new_stat(&stat, statbuf); | ||
282 | } | 270 | } |
283 | #endif | 271 | #endif |
284 | 272 | ||
@@ -404,21 +392,12 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, char __user *, filename, | |||
404 | struct stat64 __user *, statbuf, int, flag) | 392 | struct stat64 __user *, statbuf, int, flag) |
405 | { | 393 | { |
406 | struct kstat stat; | 394 | struct kstat stat; |
407 | int error = -EINVAL; | 395 | int error; |
408 | |||
409 | if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) | ||
410 | goto out; | ||
411 | |||
412 | if (flag & AT_SYMLINK_NOFOLLOW) | ||
413 | error = vfs_lstat_fd(dfd, filename, &stat); | ||
414 | else | ||
415 | error = vfs_stat_fd(dfd, filename, &stat); | ||
416 | |||
417 | if (!error) | ||
418 | error = cp_new_stat64(&stat, statbuf); | ||
419 | 396 | ||
420 | out: | 397 | error = vfs_fstatat(dfd, filename, &stat, flag); |
421 | return error; | 398 | if (error) |
399 | return error; | ||
400 | return cp_new_stat64(&stat, statbuf); | ||
422 | } | 401 | } |
423 | #endif /* __ARCH_WANT_STAT64 */ | 402 | #endif /* __ARCH_WANT_STAT64 */ |
424 | 403 | ||
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 93e0c0281d45..9345806c8853 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -157,14 +157,9 @@ static ssize_t write(struct file *file, const char __user *userbuf, | |||
157 | count = size - offs; | 157 | count = size - offs; |
158 | } | 158 | } |
159 | 159 | ||
160 | temp = kmalloc(count, GFP_KERNEL); | 160 | temp = memdup_user(userbuf, count); |
161 | if (!temp) | 161 | if (IS_ERR(temp)) |
162 | return -ENOMEM; | 162 | return PTR_ERR(temp); |
163 | |||
164 | if (copy_from_user(temp, userbuf, count)) { | ||
165 | count = -EFAULT; | ||
166 | goto out_free; | ||
167 | } | ||
168 | 163 | ||
169 | mutex_lock(&bb->mutex); | 164 | mutex_lock(&bb->mutex); |
170 | 165 | ||
@@ -176,8 +171,6 @@ static ssize_t write(struct file *file, const char __user *userbuf, | |||
176 | if (count > 0) | 171 | if (count > 0) |
177 | *off = offs + count; | 172 | *off = offs + count; |
178 | 173 | ||
179 | out_free: | ||
180 | kfree(temp); | ||
181 | return count; | 174 | return count; |
182 | } | 175 | } |
183 | 176 | ||
diff --git a/fs/xattr.c b/fs/xattr.c index 197c4fcac032..d51b8f9db921 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -237,13 +237,9 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value, | |||
237 | if (size) { | 237 | if (size) { |
238 | if (size > XATTR_SIZE_MAX) | 238 | if (size > XATTR_SIZE_MAX) |
239 | return -E2BIG; | 239 | return -E2BIG; |
240 | kvalue = kmalloc(size, GFP_KERNEL); | 240 | kvalue = memdup_user(value, size); |
241 | if (!kvalue) | 241 | if (IS_ERR(kvalue)) |
242 | return -ENOMEM; | 242 | return PTR_ERR(kvalue); |
243 | if (copy_from_user(kvalue, value, size)) { | ||
244 | kfree(kvalue); | ||
245 | return -EFAULT; | ||
246 | } | ||
247 | } | 243 | } |
248 | 244 | ||
249 | error = vfs_setxattr(d, kname, kvalue, size, flags); | 245 | error = vfs_setxattr(d, kname, kvalue, size, flags); |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index d0b499418a7d..34eaab608e6e 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -489,17 +489,12 @@ xfs_attrmulti_attr_set( | |||
489 | if (len > XATTR_SIZE_MAX) | 489 | if (len > XATTR_SIZE_MAX) |
490 | return EINVAL; | 490 | return EINVAL; |
491 | 491 | ||
492 | kbuf = kmalloc(len, GFP_KERNEL); | 492 | kbuf = memdup_user(ubuf, len); |
493 | if (!kbuf) | 493 | if (IS_ERR(kbuf)) |
494 | return ENOMEM; | 494 | return PTR_ERR(kbuf); |
495 | |||
496 | if (copy_from_user(kbuf, ubuf, len)) | ||
497 | goto out_kfree; | ||
498 | 495 | ||
499 | error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); | 496 | error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags); |
500 | 497 | ||
501 | out_kfree: | ||
502 | kfree(kbuf); | ||
503 | return error; | 498 | return error; |
504 | } | 499 | } |
505 | 500 | ||
@@ -540,20 +535,16 @@ xfs_attrmulti_by_handle( | |||
540 | if (!size || size > 16 * PAGE_SIZE) | 535 | if (!size || size > 16 * PAGE_SIZE) |
541 | goto out_dput; | 536 | goto out_dput; |
542 | 537 | ||
543 | error = ENOMEM; | 538 | ops = memdup_user(am_hreq.ops, size); |
544 | ops = kmalloc(size, GFP_KERNEL); | 539 | if (IS_ERR(ops)) { |
545 | if (!ops) | 540 | error = PTR_ERR(ops); |
546 | goto out_dput; | 541 | goto out_dput; |
547 | 542 | } | |
548 | error = EFAULT; | ||
549 | if (copy_from_user(ops, am_hreq.ops, size)) | ||
550 | goto out_kfree_ops; | ||
551 | 543 | ||
552 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); | 544 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); |
553 | if (!attr_name) | 545 | if (!attr_name) |
554 | goto out_kfree_ops; | 546 | goto out_kfree_ops; |
555 | 547 | ||
556 | |||
557 | error = 0; | 548 | error = 0; |
558 | for (i = 0; i < am_hreq.opcount; i++) { | 549 | for (i = 0; i < am_hreq.opcount; i++) { |
559 | ops[i].am_error = strncpy_from_user(attr_name, | 550 | ops[i].am_error = strncpy_from_user(attr_name, |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index c70c4e3db790..0882d166239a 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -427,20 +427,16 @@ xfs_compat_attrmulti_by_handle( | |||
427 | if (!size || size > 16 * PAGE_SIZE) | 427 | if (!size || size > 16 * PAGE_SIZE) |
428 | goto out_dput; | 428 | goto out_dput; |
429 | 429 | ||
430 | error = ENOMEM; | 430 | ops = memdup_user(compat_ptr(am_hreq.ops), size); |
431 | ops = kmalloc(size, GFP_KERNEL); | 431 | if (IS_ERR(ops)) { |
432 | if (!ops) | 432 | error = PTR_ERR(ops); |
433 | goto out_dput; | 433 | goto out_dput; |
434 | 434 | } | |
435 | error = EFAULT; | ||
436 | if (copy_from_user(ops, compat_ptr(am_hreq.ops), size)) | ||
437 | goto out_kfree_ops; | ||
438 | 435 | ||
439 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); | 436 | attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL); |
440 | if (!attr_name) | 437 | if (!attr_name) |
441 | goto out_kfree_ops; | 438 | goto out_kfree_ops; |
442 | 439 | ||
443 | |||
444 | error = 0; | 440 | error = 0; |
445 | for (i = 0; i < am_hreq.opcount; i++) { | 441 | for (i = 0; i < am_hreq.opcount; i++) { |
446 | ops[i].am_error = strncpy_from_user(attr_name, | 442 | ops[i].am_error = strncpy_from_user(attr_name, |
diff --git a/include/linux/fs.h b/include/linux/fs.h index e766be0d4329..5bed436f4353 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2299,9 +2299,8 @@ extern int vfs_readdir(struct file *, filldir_t, void *); | |||
2299 | 2299 | ||
2300 | extern int vfs_stat(char __user *, struct kstat *); | 2300 | extern int vfs_stat(char __user *, struct kstat *); |
2301 | extern int vfs_lstat(char __user *, struct kstat *); | 2301 | extern int vfs_lstat(char __user *, struct kstat *); |
2302 | extern int vfs_stat_fd(int dfd, char __user *, struct kstat *); | ||
2303 | extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *); | ||
2304 | extern int vfs_fstat(unsigned int, struct kstat *); | 2302 | extern int vfs_fstat(unsigned int, struct kstat *); |
2303 | extern int vfs_fstatat(int , char __user *, struct kstat *, int); | ||
2305 | 2304 | ||
2306 | extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | 2305 | extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, |
2307 | unsigned long arg); | 2306 | unsigned long arg); |
@@ -2449,7 +2448,7 @@ struct ctl_table; | |||
2449 | int proc_nr_files(struct ctl_table *table, int write, struct file *filp, | 2448 | int proc_nr_files(struct ctl_table *table, int write, struct file *filp, |
2450 | void __user *buffer, size_t *lenp, loff_t *ppos); | 2449 | void __user *buffer, size_t *lenp, loff_t *ppos); |
2451 | 2450 | ||
2452 | int get_filesystem_list(char * buf); | 2451 | int __init get_filesystem_list(char *buf); |
2453 | 2452 | ||
2454 | #endif /* __KERNEL__ */ | 2453 | #endif /* __KERNEL__ */ |
2455 | #endif /* _LINUX_FS_H */ | 2454 | #endif /* _LINUX_FS_H */ |
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 5621d87c4479..6b361d23a499 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h | |||
@@ -193,7 +193,7 @@ struct reiserfs_journal { | |||
193 | atomic_t j_wcount; /* count of writers for current commit */ | 193 | atomic_t j_wcount; /* count of writers for current commit */ |
194 | unsigned long j_bcount; /* batch count. allows turning X transactions into 1 */ | 194 | unsigned long j_bcount; /* batch count. allows turning X transactions into 1 */ |
195 | unsigned long j_first_unflushed_offset; /* first unflushed transactions offset */ | 195 | unsigned long j_first_unflushed_offset; /* first unflushed transactions offset */ |
196 | unsigned long j_last_flush_trans_id; /* last fully flushed journal timestamp */ | 196 | unsigned j_last_flush_trans_id; /* last fully flushed journal timestamp */ |
197 | struct buffer_head *j_header_bh; | 197 | struct buffer_head *j_header_bh; |
198 | 198 | ||
199 | time_t j_trans_start_time; /* time this transaction started */ | 199 | time_t j_trans_start_time; /* time this transaction started */ |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 917ab9525568..6e7351739a82 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -734,9 +734,6 @@ int audit_tag_tree(char *old, char *new) | |||
734 | dentry = dget(path.dentry); | 734 | dentry = dget(path.dentry); |
735 | path_put(&path); | 735 | path_put(&path); |
736 | 736 | ||
737 | if (dentry == tagged->mnt_root && dentry == mnt->mnt_root) | ||
738 | follow_up(&mnt, &dentry); | ||
739 | |||
740 | list_add_tail(&list, &tagged->mnt_list); | 737 | list_add_tail(&list, &tagged->mnt_list); |
741 | 738 | ||
742 | mutex_lock(&audit_filter_mutex); | 739 | mutex_lock(&audit_filter_mutex); |