diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 268 |
1 files changed, 138 insertions, 130 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 63ced21c12dc..7953c96a2071 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -157,13 +157,13 @@ static void __touch_mnt_namespace(struct mnt_namespace *ns) | |||
157 | 157 | ||
158 | static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) | 158 | static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) |
159 | { | 159 | { |
160 | old_nd->dentry = mnt->mnt_mountpoint; | 160 | old_nd->path.dentry = mnt->mnt_mountpoint; |
161 | old_nd->mnt = mnt->mnt_parent; | 161 | old_nd->path.mnt = mnt->mnt_parent; |
162 | mnt->mnt_parent = mnt; | 162 | mnt->mnt_parent = mnt; |
163 | mnt->mnt_mountpoint = mnt->mnt_root; | 163 | mnt->mnt_mountpoint = mnt->mnt_root; |
164 | list_del_init(&mnt->mnt_child); | 164 | list_del_init(&mnt->mnt_child); |
165 | list_del_init(&mnt->mnt_hash); | 165 | list_del_init(&mnt->mnt_hash); |
166 | old_nd->dentry->d_mounted--; | 166 | old_nd->path.dentry->d_mounted--; |
167 | } | 167 | } |
168 | 168 | ||
169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | 169 | void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, |
@@ -176,10 +176,10 @@ void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, | |||
176 | 176 | ||
177 | static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) | 177 | static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) |
178 | { | 178 | { |
179 | mnt_set_mountpoint(nd->mnt, nd->dentry, mnt); | 179 | mnt_set_mountpoint(nd->path.mnt, nd->path.dentry, mnt); |
180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + | 180 | list_add_tail(&mnt->mnt_hash, mount_hashtable + |
181 | hash(nd->mnt, nd->dentry)); | 181 | hash(nd->path.mnt, nd->path.dentry)); |
182 | list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); | 182 | list_add_tail(&mnt->mnt_child, &nd->path.mnt->mnt_mounts); |
183 | } | 183 | } |
184 | 184 | ||
185 | /* | 185 | /* |
@@ -408,10 +408,11 @@ static int show_vfsmnt(struct seq_file *m, void *v) | |||
408 | { 0, NULL } | 408 | { 0, NULL } |
409 | }; | 409 | }; |
410 | struct proc_fs_info *fs_infop; | 410 | struct proc_fs_info *fs_infop; |
411 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | ||
411 | 412 | ||
412 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); | 413 | mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); |
413 | seq_putc(m, ' '); | 414 | seq_putc(m, ' '); |
414 | seq_path(m, mnt, mnt->mnt_root, " \t\n\\"); | 415 | seq_path(m, &mnt_path, " \t\n\\"); |
415 | seq_putc(m, ' '); | 416 | seq_putc(m, ' '); |
416 | mangle(m, mnt->mnt_sb->s_type->name); | 417 | mangle(m, mnt->mnt_sb->s_type->name); |
417 | if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) { | 418 | if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) { |
@@ -443,6 +444,7 @@ struct seq_operations mounts_op = { | |||
443 | static int show_vfsstat(struct seq_file *m, void *v) | 444 | static int show_vfsstat(struct seq_file *m, void *v) |
444 | { | 445 | { |
445 | struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); | 446 | struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); |
447 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | ||
446 | int err = 0; | 448 | int err = 0; |
447 | 449 | ||
448 | /* device */ | 450 | /* device */ |
@@ -454,7 +456,7 @@ static int show_vfsstat(struct seq_file *m, void *v) | |||
454 | 456 | ||
455 | /* mount point */ | 457 | /* mount point */ |
456 | seq_puts(m, " mounted on "); | 458 | seq_puts(m, " mounted on "); |
457 | seq_path(m, mnt, mnt->mnt_root, " \t\n\\"); | 459 | seq_path(m, &mnt_path, " \t\n\\"); |
458 | seq_putc(m, ' '); | 460 | seq_putc(m, ' '); |
459 | 461 | ||
460 | /* file system type */ | 462 | /* file system type */ |
@@ -593,7 +595,7 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
593 | * (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount] | 595 | * (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount] |
594 | */ | 596 | */ |
595 | if (flags & MNT_EXPIRE) { | 597 | if (flags & MNT_EXPIRE) { |
596 | if (mnt == current->fs->rootmnt || | 598 | if (mnt == current->fs->root.mnt || |
597 | flags & (MNT_FORCE | MNT_DETACH)) | 599 | flags & (MNT_FORCE | MNT_DETACH)) |
598 | return -EINVAL; | 600 | return -EINVAL; |
599 | 601 | ||
@@ -628,7 +630,7 @@ static int do_umount(struct vfsmount *mnt, int flags) | |||
628 | * /reboot - static binary that would close all descriptors and | 630 | * /reboot - static binary that would close all descriptors and |
629 | * call reboot(9). Then init(8) could umount root and exec /reboot. | 631 | * call reboot(9). Then init(8) could umount root and exec /reboot. |
630 | */ | 632 | */ |
631 | if (mnt == current->fs->rootmnt && !(flags & MNT_DETACH)) { | 633 | if (mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) { |
632 | /* | 634 | /* |
633 | * Special case for "unmounting" root ... | 635 | * Special case for "unmounting" root ... |
634 | * we just try to remount it readonly. | 636 | * we just try to remount it readonly. |
@@ -679,18 +681,20 @@ asmlinkage long sys_umount(char __user * name, int flags) | |||
679 | if (retval) | 681 | if (retval) |
680 | goto out; | 682 | goto out; |
681 | retval = -EINVAL; | 683 | retval = -EINVAL; |
682 | if (nd.dentry != nd.mnt->mnt_root) | 684 | if (nd.path.dentry != nd.path.mnt->mnt_root) |
683 | goto dput_and_out; | 685 | goto dput_and_out; |
684 | if (!check_mnt(nd.mnt)) | 686 | if (!check_mnt(nd.path.mnt)) |
685 | goto dput_and_out; | 687 | goto dput_and_out; |
686 | 688 | ||
687 | retval = -EPERM; | 689 | retval = -EPERM; |
688 | if (!capable(CAP_SYS_ADMIN)) | 690 | if (!capable(CAP_SYS_ADMIN)) |
689 | goto dput_and_out; | 691 | goto dput_and_out; |
690 | 692 | ||
691 | retval = do_umount(nd.mnt, flags); | 693 | retval = do_umount(nd.path.mnt, flags); |
692 | dput_and_out: | 694 | dput_and_out: |
693 | path_release_on_umount(&nd); | 695 | /* we mustn't call path_put() as that would clear mnt_expiry_mark */ |
696 | dput(nd.path.dentry); | ||
697 | mntput_no_expire(nd.path.mnt); | ||
694 | out: | 698 | out: |
695 | return retval; | 699 | return retval; |
696 | } | 700 | } |
@@ -713,10 +717,10 @@ static int mount_is_safe(struct nameidata *nd) | |||
713 | return 0; | 717 | return 0; |
714 | return -EPERM; | 718 | return -EPERM; |
715 | #ifdef notyet | 719 | #ifdef notyet |
716 | if (S_ISLNK(nd->dentry->d_inode->i_mode)) | 720 | if (S_ISLNK(nd->path.dentry->d_inode->i_mode)) |
717 | return -EPERM; | 721 | return -EPERM; |
718 | if (nd->dentry->d_inode->i_mode & S_ISVTX) { | 722 | if (nd->path.dentry->d_inode->i_mode & S_ISVTX) { |
719 | if (current->uid != nd->dentry->d_inode->i_uid) | 723 | if (current->uid != nd->path.dentry->d_inode->i_uid) |
720 | return -EPERM; | 724 | return -EPERM; |
721 | } | 725 | } |
722 | if (vfs_permission(nd, MAY_WRITE)) | 726 | if (vfs_permission(nd, MAY_WRITE)) |
@@ -765,8 +769,8 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | |||
765 | q = q->mnt_parent; | 769 | q = q->mnt_parent; |
766 | } | 770 | } |
767 | p = s; | 771 | p = s; |
768 | nd.mnt = q; | 772 | nd.path.mnt = q; |
769 | nd.dentry = p->mnt_mountpoint; | 773 | nd.path.dentry = p->mnt_mountpoint; |
770 | q = clone_mnt(p, p->mnt_root, flag); | 774 | q = clone_mnt(p, p->mnt_root, flag); |
771 | if (!q) | 775 | if (!q) |
772 | goto Enomem; | 776 | goto Enomem; |
@@ -875,8 +879,8 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
875 | struct nameidata *nd, struct nameidata *parent_nd) | 879 | struct nameidata *nd, struct nameidata *parent_nd) |
876 | { | 880 | { |
877 | LIST_HEAD(tree_list); | 881 | LIST_HEAD(tree_list); |
878 | struct vfsmount *dest_mnt = nd->mnt; | 882 | struct vfsmount *dest_mnt = nd->path.mnt; |
879 | struct dentry *dest_dentry = nd->dentry; | 883 | struct dentry *dest_dentry = nd->path.dentry; |
880 | struct vfsmount *child, *p; | 884 | struct vfsmount *child, *p; |
881 | 885 | ||
882 | if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) | 886 | if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) |
@@ -911,13 +915,13 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) | |||
911 | if (mnt->mnt_sb->s_flags & MS_NOUSER) | 915 | if (mnt->mnt_sb->s_flags & MS_NOUSER) |
912 | return -EINVAL; | 916 | return -EINVAL; |
913 | 917 | ||
914 | if (S_ISDIR(nd->dentry->d_inode->i_mode) != | 918 | if (S_ISDIR(nd->path.dentry->d_inode->i_mode) != |
915 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) | 919 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) |
916 | return -ENOTDIR; | 920 | return -ENOTDIR; |
917 | 921 | ||
918 | err = -ENOENT; | 922 | err = -ENOENT; |
919 | mutex_lock(&nd->dentry->d_inode->i_mutex); | 923 | mutex_lock(&nd->path.dentry->d_inode->i_mutex); |
920 | if (IS_DEADDIR(nd->dentry->d_inode)) | 924 | if (IS_DEADDIR(nd->path.dentry->d_inode)) |
921 | goto out_unlock; | 925 | goto out_unlock; |
922 | 926 | ||
923 | err = security_sb_check_sb(mnt, nd); | 927 | err = security_sb_check_sb(mnt, nd); |
@@ -925,10 +929,10 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) | |||
925 | goto out_unlock; | 929 | goto out_unlock; |
926 | 930 | ||
927 | err = -ENOENT; | 931 | err = -ENOENT; |
928 | if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) | 932 | if (IS_ROOT(nd->path.dentry) || !d_unhashed(nd->path.dentry)) |
929 | err = attach_recursive_mnt(mnt, nd, NULL); | 933 | err = attach_recursive_mnt(mnt, nd, NULL); |
930 | out_unlock: | 934 | out_unlock: |
931 | mutex_unlock(&nd->dentry->d_inode->i_mutex); | 935 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); |
932 | if (!err) | 936 | if (!err) |
933 | security_sb_post_addmount(mnt, nd); | 937 | security_sb_post_addmount(mnt, nd); |
934 | return err; | 938 | return err; |
@@ -940,14 +944,14 @@ out_unlock: | |||
940 | */ | 944 | */ |
941 | static noinline int do_change_type(struct nameidata *nd, int flag) | 945 | static noinline int do_change_type(struct nameidata *nd, int flag) |
942 | { | 946 | { |
943 | struct vfsmount *m, *mnt = nd->mnt; | 947 | struct vfsmount *m, *mnt = nd->path.mnt; |
944 | int recurse = flag & MS_REC; | 948 | int recurse = flag & MS_REC; |
945 | int type = flag & ~MS_REC; | 949 | int type = flag & ~MS_REC; |
946 | 950 | ||
947 | if (!capable(CAP_SYS_ADMIN)) | 951 | if (!capable(CAP_SYS_ADMIN)) |
948 | return -EPERM; | 952 | return -EPERM; |
949 | 953 | ||
950 | if (nd->dentry != nd->mnt->mnt_root) | 954 | if (nd->path.dentry != nd->path.mnt->mnt_root) |
951 | return -EINVAL; | 955 | return -EINVAL; |
952 | 956 | ||
953 | down_write(&namespace_sem); | 957 | down_write(&namespace_sem); |
@@ -979,17 +983,17 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name, | |||
979 | 983 | ||
980 | down_write(&namespace_sem); | 984 | down_write(&namespace_sem); |
981 | err = -EINVAL; | 985 | err = -EINVAL; |
982 | if (IS_MNT_UNBINDABLE(old_nd.mnt)) | 986 | if (IS_MNT_UNBINDABLE(old_nd.path.mnt)) |
983 | goto out; | 987 | goto out; |
984 | 988 | ||
985 | if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) | 989 | if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) |
986 | goto out; | 990 | goto out; |
987 | 991 | ||
988 | err = -ENOMEM; | 992 | err = -ENOMEM; |
989 | if (recurse) | 993 | if (recurse) |
990 | mnt = copy_tree(old_nd.mnt, old_nd.dentry, 0); | 994 | mnt = copy_tree(old_nd.path.mnt, old_nd.path.dentry, 0); |
991 | else | 995 | else |
992 | mnt = clone_mnt(old_nd.mnt, old_nd.dentry, 0); | 996 | mnt = clone_mnt(old_nd.path.mnt, old_nd.path.dentry, 0); |
993 | 997 | ||
994 | if (!mnt) | 998 | if (!mnt) |
995 | goto out; | 999 | goto out; |
@@ -1005,7 +1009,7 @@ static noinline int do_loopback(struct nameidata *nd, char *old_name, | |||
1005 | 1009 | ||
1006 | out: | 1010 | out: |
1007 | up_write(&namespace_sem); | 1011 | up_write(&namespace_sem); |
1008 | path_release(&old_nd); | 1012 | path_put(&old_nd.path); |
1009 | return err; | 1013 | return err; |
1010 | } | 1014 | } |
1011 | 1015 | ||
@@ -1019,24 +1023,24 @@ static noinline int do_remount(struct nameidata *nd, int flags, int mnt_flags, | |||
1019 | void *data) | 1023 | void *data) |
1020 | { | 1024 | { |
1021 | int err; | 1025 | int err; |
1022 | struct super_block *sb = nd->mnt->mnt_sb; | 1026 | struct super_block *sb = nd->path.mnt->mnt_sb; |
1023 | 1027 | ||
1024 | if (!capable(CAP_SYS_ADMIN)) | 1028 | if (!capable(CAP_SYS_ADMIN)) |
1025 | return -EPERM; | 1029 | return -EPERM; |
1026 | 1030 | ||
1027 | if (!check_mnt(nd->mnt)) | 1031 | if (!check_mnt(nd->path.mnt)) |
1028 | return -EINVAL; | 1032 | return -EINVAL; |
1029 | 1033 | ||
1030 | if (nd->dentry != nd->mnt->mnt_root) | 1034 | if (nd->path.dentry != nd->path.mnt->mnt_root) |
1031 | return -EINVAL; | 1035 | return -EINVAL; |
1032 | 1036 | ||
1033 | down_write(&sb->s_umount); | 1037 | down_write(&sb->s_umount); |
1034 | err = do_remount_sb(sb, flags, data, 0); | 1038 | err = do_remount_sb(sb, flags, data, 0); |
1035 | if (!err) | 1039 | if (!err) |
1036 | nd->mnt->mnt_flags = mnt_flags; | 1040 | nd->path.mnt->mnt_flags = mnt_flags; |
1037 | up_write(&sb->s_umount); | 1041 | up_write(&sb->s_umount); |
1038 | if (!err) | 1042 | if (!err) |
1039 | security_sb_post_remount(nd->mnt, flags, data); | 1043 | security_sb_post_remount(nd->path.mnt, flags, data); |
1040 | return err; | 1044 | return err; |
1041 | } | 1045 | } |
1042 | 1046 | ||
@@ -1067,61 +1071,65 @@ static noinline int do_move_mount(struct nameidata *nd, char *old_name) | |||
1067 | return err; | 1071 | return err; |
1068 | 1072 | ||
1069 | down_write(&namespace_sem); | 1073 | down_write(&namespace_sem); |
1070 | while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) | 1074 | while (d_mountpoint(nd->path.dentry) && |
1075 | follow_down(&nd->path.mnt, &nd->path.dentry)) | ||
1071 | ; | 1076 | ; |
1072 | err = -EINVAL; | 1077 | err = -EINVAL; |
1073 | if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) | 1078 | if (!check_mnt(nd->path.mnt) || !check_mnt(old_nd.path.mnt)) |
1074 | goto out; | 1079 | goto out; |
1075 | 1080 | ||
1076 | err = -ENOENT; | 1081 | err = -ENOENT; |
1077 | mutex_lock(&nd->dentry->d_inode->i_mutex); | 1082 | mutex_lock(&nd->path.dentry->d_inode->i_mutex); |
1078 | if (IS_DEADDIR(nd->dentry->d_inode)) | 1083 | if (IS_DEADDIR(nd->path.dentry->d_inode)) |
1079 | goto out1; | 1084 | goto out1; |
1080 | 1085 | ||
1081 | if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry)) | 1086 | if (!IS_ROOT(nd->path.dentry) && d_unhashed(nd->path.dentry)) |
1082 | goto out1; | 1087 | goto out1; |
1083 | 1088 | ||
1084 | err = -EINVAL; | 1089 | err = -EINVAL; |
1085 | if (old_nd.dentry != old_nd.mnt->mnt_root) | 1090 | if (old_nd.path.dentry != old_nd.path.mnt->mnt_root) |
1086 | goto out1; | 1091 | goto out1; |
1087 | 1092 | ||
1088 | if (old_nd.mnt == old_nd.mnt->mnt_parent) | 1093 | if (old_nd.path.mnt == old_nd.path.mnt->mnt_parent) |
1089 | goto out1; | 1094 | goto out1; |
1090 | 1095 | ||
1091 | if (S_ISDIR(nd->dentry->d_inode->i_mode) != | 1096 | if (S_ISDIR(nd->path.dentry->d_inode->i_mode) != |
1092 | S_ISDIR(old_nd.dentry->d_inode->i_mode)) | 1097 | S_ISDIR(old_nd.path.dentry->d_inode->i_mode)) |
1093 | goto out1; | 1098 | goto out1; |
1094 | /* | 1099 | /* |
1095 | * Don't move a mount residing in a shared parent. | 1100 | * Don't move a mount residing in a shared parent. |
1096 | */ | 1101 | */ |
1097 | if (old_nd.mnt->mnt_parent && IS_MNT_SHARED(old_nd.mnt->mnt_parent)) | 1102 | if (old_nd.path.mnt->mnt_parent && |
1103 | IS_MNT_SHARED(old_nd.path.mnt->mnt_parent)) | ||
1098 | goto out1; | 1104 | goto out1; |
1099 | /* | 1105 | /* |
1100 | * Don't move a mount tree containing unbindable mounts to a destination | 1106 | * Don't move a mount tree containing unbindable mounts to a destination |
1101 | * mount which is shared. | 1107 | * mount which is shared. |
1102 | */ | 1108 | */ |
1103 | if (IS_MNT_SHARED(nd->mnt) && tree_contains_unbindable(old_nd.mnt)) | 1109 | if (IS_MNT_SHARED(nd->path.mnt) && |
1110 | tree_contains_unbindable(old_nd.path.mnt)) | ||
1104 | goto out1; | 1111 | goto out1; |
1105 | err = -ELOOP; | 1112 | err = -ELOOP; |
1106 | for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent) | 1113 | for (p = nd->path.mnt; p->mnt_parent != p; p = p->mnt_parent) |
1107 | if (p == old_nd.mnt) | 1114 | if (p == old_nd.path.mnt) |
1108 | goto out1; | 1115 | goto out1; |
1109 | 1116 | ||
1110 | if ((err = attach_recursive_mnt(old_nd.mnt, nd, &parent_nd))) | 1117 | err = attach_recursive_mnt(old_nd.path.mnt, nd, &parent_nd); |
1118 | if (err) | ||
1111 | goto out1; | 1119 | goto out1; |
1112 | 1120 | ||
1113 | spin_lock(&vfsmount_lock); | 1121 | spin_lock(&vfsmount_lock); |
1114 | /* if the mount is moved, it should no longer be expire | 1122 | /* if the mount is moved, it should no longer be expire |
1115 | * automatically */ | 1123 | * automatically */ |
1116 | list_del_init(&old_nd.mnt->mnt_expire); | 1124 | list_del_init(&old_nd.path.mnt->mnt_expire); |
1117 | spin_unlock(&vfsmount_lock); | 1125 | spin_unlock(&vfsmount_lock); |
1118 | out1: | 1126 | out1: |
1119 | mutex_unlock(&nd->dentry->d_inode->i_mutex); | 1127 | mutex_unlock(&nd->path.dentry->d_inode->i_mutex); |
1120 | out: | 1128 | out: |
1121 | up_write(&namespace_sem); | 1129 | up_write(&namespace_sem); |
1122 | if (!err) | 1130 | if (!err) |
1123 | path_release(&parent_nd); | 1131 | path_put(&parent_nd.path); |
1124 | path_release(&old_nd); | 1132 | path_put(&old_nd.path); |
1125 | return err; | 1133 | return err; |
1126 | } | 1134 | } |
1127 | 1135 | ||
@@ -1160,16 +1168,17 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, | |||
1160 | 1168 | ||
1161 | down_write(&namespace_sem); | 1169 | down_write(&namespace_sem); |
1162 | /* Something was mounted here while we slept */ | 1170 | /* Something was mounted here while we slept */ |
1163 | while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) | 1171 | while (d_mountpoint(nd->path.dentry) && |
1172 | follow_down(&nd->path.mnt, &nd->path.dentry)) | ||
1164 | ; | 1173 | ; |
1165 | err = -EINVAL; | 1174 | err = -EINVAL; |
1166 | if (!check_mnt(nd->mnt)) | 1175 | if (!check_mnt(nd->path.mnt)) |
1167 | goto unlock; | 1176 | goto unlock; |
1168 | 1177 | ||
1169 | /* Refuse the same filesystem on the same mount point */ | 1178 | /* Refuse the same filesystem on the same mount point */ |
1170 | err = -EBUSY; | 1179 | err = -EBUSY; |
1171 | if (nd->mnt->mnt_sb == newmnt->mnt_sb && | 1180 | if (nd->path.mnt->mnt_sb == newmnt->mnt_sb && |
1172 | nd->mnt->mnt_root == nd->dentry) | 1181 | nd->path.mnt->mnt_root == nd->path.dentry) |
1173 | goto unlock; | 1182 | goto unlock; |
1174 | 1183 | ||
1175 | err = -EINVAL; | 1184 | err = -EINVAL; |
@@ -1505,7 +1514,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1505 | retval = do_new_mount(&nd, type_page, flags, mnt_flags, | 1514 | retval = do_new_mount(&nd, type_page, flags, mnt_flags, |
1506 | dev_name, data_page); | 1515 | dev_name, data_page); |
1507 | dput_out: | 1516 | dput_out: |
1508 | path_release(&nd); | 1517 | path_put(&nd.path); |
1509 | return retval; | 1518 | return retval; |
1510 | } | 1519 | } |
1511 | 1520 | ||
@@ -1552,17 +1561,17 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
1552 | while (p) { | 1561 | while (p) { |
1553 | q->mnt_ns = new_ns; | 1562 | q->mnt_ns = new_ns; |
1554 | if (fs) { | 1563 | if (fs) { |
1555 | if (p == fs->rootmnt) { | 1564 | if (p == fs->root.mnt) { |
1556 | rootmnt = p; | 1565 | rootmnt = p; |
1557 | fs->rootmnt = mntget(q); | 1566 | fs->root.mnt = mntget(q); |
1558 | } | 1567 | } |
1559 | if (p == fs->pwdmnt) { | 1568 | if (p == fs->pwd.mnt) { |
1560 | pwdmnt = p; | 1569 | pwdmnt = p; |
1561 | fs->pwdmnt = mntget(q); | 1570 | fs->pwd.mnt = mntget(q); |
1562 | } | 1571 | } |
1563 | if (p == fs->altrootmnt) { | 1572 | if (p == fs->altroot.mnt) { |
1564 | altrootmnt = p; | 1573 | altrootmnt = p; |
1565 | fs->altrootmnt = mntget(q); | 1574 | fs->altroot.mnt = mntget(q); |
1566 | } | 1575 | } |
1567 | } | 1576 | } |
1568 | p = next_mnt(p, mnt_ns->root); | 1577 | p = next_mnt(p, mnt_ns->root); |
@@ -1643,44 +1652,35 @@ out1: | |||
1643 | * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. | 1652 | * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. |
1644 | * It can block. Requires the big lock held. | 1653 | * It can block. Requires the big lock held. |
1645 | */ | 1654 | */ |
1646 | void set_fs_root(struct fs_struct *fs, struct vfsmount *mnt, | 1655 | void set_fs_root(struct fs_struct *fs, struct path *path) |
1647 | struct dentry *dentry) | ||
1648 | { | 1656 | { |
1649 | struct dentry *old_root; | 1657 | struct path old_root; |
1650 | struct vfsmount *old_rootmnt; | 1658 | |
1651 | write_lock(&fs->lock); | 1659 | write_lock(&fs->lock); |
1652 | old_root = fs->root; | 1660 | old_root = fs->root; |
1653 | old_rootmnt = fs->rootmnt; | 1661 | fs->root = *path; |
1654 | fs->rootmnt = mntget(mnt); | 1662 | path_get(path); |
1655 | fs->root = dget(dentry); | ||
1656 | write_unlock(&fs->lock); | 1663 | write_unlock(&fs->lock); |
1657 | if (old_root) { | 1664 | if (old_root.dentry) |
1658 | dput(old_root); | 1665 | path_put(&old_root); |
1659 | mntput(old_rootmnt); | ||
1660 | } | ||
1661 | } | 1666 | } |
1662 | 1667 | ||
1663 | /* | 1668 | /* |
1664 | * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. | 1669 | * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. |
1665 | * It can block. Requires the big lock held. | 1670 | * It can block. Requires the big lock held. |
1666 | */ | 1671 | */ |
1667 | void set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, | 1672 | void set_fs_pwd(struct fs_struct *fs, struct path *path) |
1668 | struct dentry *dentry) | ||
1669 | { | 1673 | { |
1670 | struct dentry *old_pwd; | 1674 | struct path old_pwd; |
1671 | struct vfsmount *old_pwdmnt; | ||
1672 | 1675 | ||
1673 | write_lock(&fs->lock); | 1676 | write_lock(&fs->lock); |
1674 | old_pwd = fs->pwd; | 1677 | old_pwd = fs->pwd; |
1675 | old_pwdmnt = fs->pwdmnt; | 1678 | fs->pwd = *path; |
1676 | fs->pwdmnt = mntget(mnt); | 1679 | path_get(path); |
1677 | fs->pwd = dget(dentry); | ||
1678 | write_unlock(&fs->lock); | 1680 | write_unlock(&fs->lock); |
1679 | 1681 | ||
1680 | if (old_pwd) { | 1682 | if (old_pwd.dentry) |
1681 | dput(old_pwd); | 1683 | path_put(&old_pwd); |
1682 | mntput(old_pwdmnt); | ||
1683 | } | ||
1684 | } | 1684 | } |
1685 | 1685 | ||
1686 | static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) | 1686 | static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) |
@@ -1695,12 +1695,12 @@ static void chroot_fs_refs(struct nameidata *old_nd, struct nameidata *new_nd) | |||
1695 | if (fs) { | 1695 | if (fs) { |
1696 | atomic_inc(&fs->count); | 1696 | atomic_inc(&fs->count); |
1697 | task_unlock(p); | 1697 | task_unlock(p); |
1698 | if (fs->root == old_nd->dentry | 1698 | if (fs->root.dentry == old_nd->path.dentry |
1699 | && fs->rootmnt == old_nd->mnt) | 1699 | && fs->root.mnt == old_nd->path.mnt) |
1700 | set_fs_root(fs, new_nd->mnt, new_nd->dentry); | 1700 | set_fs_root(fs, &new_nd->path); |
1701 | if (fs->pwd == old_nd->dentry | 1701 | if (fs->pwd.dentry == old_nd->path.dentry |
1702 | && fs->pwdmnt == old_nd->mnt) | 1702 | && fs->pwd.mnt == old_nd->path.mnt) |
1703 | set_fs_pwd(fs, new_nd->mnt, new_nd->dentry); | 1703 | set_fs_pwd(fs, &new_nd->path); |
1704 | put_fs_struct(fs); | 1704 | put_fs_struct(fs); |
1705 | } else | 1705 | } else |
1706 | task_unlock(p); | 1706 | task_unlock(p); |
@@ -1750,7 +1750,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1750 | if (error) | 1750 | if (error) |
1751 | goto out0; | 1751 | goto out0; |
1752 | error = -EINVAL; | 1752 | error = -EINVAL; |
1753 | if (!check_mnt(new_nd.mnt)) | 1753 | if (!check_mnt(new_nd.path.mnt)) |
1754 | goto out1; | 1754 | goto out1; |
1755 | 1755 | ||
1756 | error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd); | 1756 | error = __user_walk(put_old, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old_nd); |
@@ -1759,74 +1759,78 @@ asmlinkage long sys_pivot_root(const char __user * new_root, | |||
1759 | 1759 | ||
1760 | error = security_sb_pivotroot(&old_nd, &new_nd); | 1760 | error = security_sb_pivotroot(&old_nd, &new_nd); |
1761 | if (error) { | 1761 | if (error) { |
1762 | path_release(&old_nd); | 1762 | path_put(&old_nd.path); |
1763 | goto out1; | 1763 | goto out1; |
1764 | } | 1764 | } |
1765 | 1765 | ||
1766 | read_lock(¤t->fs->lock); | 1766 | read_lock(¤t->fs->lock); |
1767 | user_nd.mnt = mntget(current->fs->rootmnt); | 1767 | user_nd.path = current->fs->root; |
1768 | user_nd.dentry = dget(current->fs->root); | 1768 | path_get(¤t->fs->root); |
1769 | read_unlock(¤t->fs->lock); | 1769 | read_unlock(¤t->fs->lock); |
1770 | down_write(&namespace_sem); | 1770 | down_write(&namespace_sem); |
1771 | mutex_lock(&old_nd.dentry->d_inode->i_mutex); | 1771 | mutex_lock(&old_nd.path.dentry->d_inode->i_mutex); |
1772 | error = -EINVAL; | 1772 | error = -EINVAL; |
1773 | if (IS_MNT_SHARED(old_nd.mnt) || | 1773 | if (IS_MNT_SHARED(old_nd.path.mnt) || |
1774 | IS_MNT_SHARED(new_nd.mnt->mnt_parent) || | 1774 | IS_MNT_SHARED(new_nd.path.mnt->mnt_parent) || |
1775 | IS_MNT_SHARED(user_nd.mnt->mnt_parent)) | 1775 | IS_MNT_SHARED(user_nd.path.mnt->mnt_parent)) |
1776 | goto out2; | 1776 | goto out2; |
1777 | if (!check_mnt(user_nd.mnt)) | 1777 | if (!check_mnt(user_nd.path.mnt)) |
1778 | goto out2; | 1778 | goto out2; |
1779 | error = -ENOENT; | 1779 | error = -ENOENT; |
1780 | if (IS_DEADDIR(new_nd.dentry->d_inode)) | 1780 | if (IS_DEADDIR(new_nd.path.dentry->d_inode)) |
1781 | goto out2; | 1781 | goto out2; |
1782 | if (d_unhashed(new_nd.dentry) && !IS_ROOT(new_nd.dentry)) | 1782 | if (d_unhashed(new_nd.path.dentry) && !IS_ROOT(new_nd.path.dentry)) |
1783 | goto out2; | 1783 | goto out2; |
1784 | if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry)) | 1784 | if (d_unhashed(old_nd.path.dentry) && !IS_ROOT(old_nd.path.dentry)) |
1785 | goto out2; | 1785 | goto out2; |
1786 | error = -EBUSY; | 1786 | error = -EBUSY; |
1787 | if (new_nd.mnt == user_nd.mnt || old_nd.mnt == user_nd.mnt) | 1787 | if (new_nd.path.mnt == user_nd.path.mnt || |
1788 | old_nd.path.mnt == user_nd.path.mnt) | ||
1788 | goto out2; /* loop, on the same file system */ | 1789 | goto out2; /* loop, on the same file system */ |
1789 | error = -EINVAL; | 1790 | error = -EINVAL; |
1790 | if (user_nd.mnt->mnt_root != user_nd.dentry) | 1791 | if (user_nd.path.mnt->mnt_root != user_nd.path.dentry) |
1791 | goto out2; /* not a mountpoint */ | 1792 | goto out2; /* not a mountpoint */ |
1792 | if (user_nd.mnt->mnt_parent == user_nd.mnt) | 1793 | if (user_nd.path.mnt->mnt_parent == user_nd.path.mnt) |
1793 | goto out2; /* not attached */ | 1794 | goto out2; /* not attached */ |
1794 | if (new_nd.mnt->mnt_root != new_nd.dentry) | 1795 | if (new_nd.path.mnt->mnt_root != new_nd.path.dentry) |
1795 | goto out2; /* not a mountpoint */ | 1796 | goto out2; /* not a mountpoint */ |
1796 | if (new_nd.mnt->mnt_parent == new_nd.mnt) | 1797 | if (new_nd.path.mnt->mnt_parent == new_nd.path.mnt) |
1797 | goto out2; /* not attached */ | 1798 | goto out2; /* not attached */ |
1798 | tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */ | 1799 | /* make sure we can reach put_old from new_root */ |
1800 | tmp = old_nd.path.mnt; | ||
1799 | spin_lock(&vfsmount_lock); | 1801 | spin_lock(&vfsmount_lock); |
1800 | if (tmp != new_nd.mnt) { | 1802 | if (tmp != new_nd.path.mnt) { |
1801 | for (;;) { | 1803 | for (;;) { |
1802 | if (tmp->mnt_parent == tmp) | 1804 | if (tmp->mnt_parent == tmp) |
1803 | goto out3; /* already mounted on put_old */ | 1805 | goto out3; /* already mounted on put_old */ |
1804 | if (tmp->mnt_parent == new_nd.mnt) | 1806 | if (tmp->mnt_parent == new_nd.path.mnt) |
1805 | break; | 1807 | break; |
1806 | tmp = tmp->mnt_parent; | 1808 | tmp = tmp->mnt_parent; |
1807 | } | 1809 | } |
1808 | if (!is_subdir(tmp->mnt_mountpoint, new_nd.dentry)) | 1810 | if (!is_subdir(tmp->mnt_mountpoint, new_nd.path.dentry)) |
1809 | goto out3; | 1811 | goto out3; |
1810 | } else if (!is_subdir(old_nd.dentry, new_nd.dentry)) | 1812 | } else if (!is_subdir(old_nd.path.dentry, new_nd.path.dentry)) |
1811 | goto out3; | 1813 | goto out3; |
1812 | detach_mnt(new_nd.mnt, &parent_nd); | 1814 | detach_mnt(new_nd.path.mnt, &parent_nd); |
1813 | detach_mnt(user_nd.mnt, &root_parent); | 1815 | detach_mnt(user_nd.path.mnt, &root_parent); |
1814 | attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ | 1816 | /* mount old root on put_old */ |
1815 | attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ | 1817 | attach_mnt(user_nd.path.mnt, &old_nd); |
1818 | /* mount new_root on / */ | ||
1819 | attach_mnt(new_nd.path.mnt, &root_parent); | ||
1816 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 1820 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
1817 | spin_unlock(&vfsmount_lock); | 1821 | spin_unlock(&vfsmount_lock); |
1818 | chroot_fs_refs(&user_nd, &new_nd); | 1822 | chroot_fs_refs(&user_nd, &new_nd); |
1819 | security_sb_post_pivotroot(&user_nd, &new_nd); | 1823 | security_sb_post_pivotroot(&user_nd, &new_nd); |
1820 | error = 0; | 1824 | error = 0; |
1821 | path_release(&root_parent); | 1825 | path_put(&root_parent.path); |
1822 | path_release(&parent_nd); | 1826 | path_put(&parent_nd.path); |
1823 | out2: | 1827 | out2: |
1824 | mutex_unlock(&old_nd.dentry->d_inode->i_mutex); | 1828 | mutex_unlock(&old_nd.path.dentry->d_inode->i_mutex); |
1825 | up_write(&namespace_sem); | 1829 | up_write(&namespace_sem); |
1826 | path_release(&user_nd); | 1830 | path_put(&user_nd.path); |
1827 | path_release(&old_nd); | 1831 | path_put(&old_nd.path); |
1828 | out1: | 1832 | out1: |
1829 | path_release(&new_nd); | 1833 | path_put(&new_nd.path); |
1830 | out0: | 1834 | out0: |
1831 | unlock_kernel(); | 1835 | unlock_kernel(); |
1832 | return error; | 1836 | return error; |
@@ -1839,6 +1843,7 @@ static void __init init_mount_tree(void) | |||
1839 | { | 1843 | { |
1840 | struct vfsmount *mnt; | 1844 | struct vfsmount *mnt; |
1841 | struct mnt_namespace *ns; | 1845 | struct mnt_namespace *ns; |
1846 | struct path root; | ||
1842 | 1847 | ||
1843 | mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); | 1848 | mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); |
1844 | if (IS_ERR(mnt)) | 1849 | if (IS_ERR(mnt)) |
@@ -1857,8 +1862,11 @@ static void __init init_mount_tree(void) | |||
1857 | init_task.nsproxy->mnt_ns = ns; | 1862 | init_task.nsproxy->mnt_ns = ns; |
1858 | get_mnt_ns(ns); | 1863 | get_mnt_ns(ns); |
1859 | 1864 | ||
1860 | set_fs_pwd(current->fs, ns->root, ns->root->mnt_root); | 1865 | root.mnt = ns->root; |
1861 | set_fs_root(current->fs, ns->root, ns->root->mnt_root); | 1866 | root.dentry = ns->root->mnt_root; |
1867 | |||
1868 | set_fs_pwd(current->fs, &root); | ||
1869 | set_fs_root(current->fs, &root); | ||
1862 | } | 1870 | } |
1863 | 1871 | ||
1864 | void __init mnt_init(void) | 1872 | void __init mnt_init(void) |