diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-09-11 08:46:53 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-09-11 08:46:53 -0400 |
commit | 336879b1da97fffc097f77c6d6f818660f2826f0 (patch) | |
tree | 4ddb4d1c5d2b67fb096c72e41d2a03b01a605041 /fs/namespace.c | |
parent | 3d3cbd84300e7be1e53083cac0f6f9c12978ecb4 (diff) | |
parent | fdcaa1dbb7c6ed419b10fb8cdb5001ab0a00538f (diff) |
Merge remote-tracking branch 'airlied/drm-next' into topic/vblank-rework
Dave asked me to do the backmerge before sending him the revised pull
request, so here we go. Nothing fancy in the conflicts, just a few
things changed right next to each another.
Conflicts:
drivers/gpu/drm/drm_irq.c
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 132 |
1 files changed, 88 insertions, 44 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index 182bc41cd887..a01c7730e9af 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
17 | #include <linux/security.h> | 17 | #include <linux/security.h> |
18 | #include <linux/idr.h> | 18 | #include <linux/idr.h> |
19 | #include <linux/acct.h> /* acct_auto_close_mnt */ | ||
20 | #include <linux/init.h> /* init_rootfs */ | 19 | #include <linux/init.h> /* init_rootfs */ |
21 | #include <linux/fs_struct.h> /* get_fs_root et.al. */ | 20 | #include <linux/fs_struct.h> /* get_fs_root et.al. */ |
22 | #include <linux/fsnotify.h> /* fsnotify_vfsmount_delete */ | 21 | #include <linux/fsnotify.h> /* fsnotify_vfsmount_delete */ |
@@ -779,6 +778,20 @@ static void attach_mnt(struct mount *mnt, | |||
779 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | 778 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); |
780 | } | 779 | } |
781 | 780 | ||
781 | static void attach_shadowed(struct mount *mnt, | ||
782 | struct mount *parent, | ||
783 | struct mount *shadows) | ||
784 | { | ||
785 | if (shadows) { | ||
786 | hlist_add_behind_rcu(&mnt->mnt_hash, &shadows->mnt_hash); | ||
787 | list_add(&mnt->mnt_child, &shadows->mnt_child); | ||
788 | } else { | ||
789 | hlist_add_head_rcu(&mnt->mnt_hash, | ||
790 | m_hash(&parent->mnt, mnt->mnt_mountpoint)); | ||
791 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | ||
792 | } | ||
793 | } | ||
794 | |||
782 | /* | 795 | /* |
783 | * vfsmount lock must be held for write | 796 | * vfsmount lock must be held for write |
784 | */ | 797 | */ |
@@ -797,12 +810,7 @@ static void commit_tree(struct mount *mnt, struct mount *shadows) | |||
797 | 810 | ||
798 | list_splice(&head, n->list.prev); | 811 | list_splice(&head, n->list.prev); |
799 | 812 | ||
800 | if (shadows) | 813 | attach_shadowed(mnt, parent, shadows); |
801 | hlist_add_after_rcu(&shadows->mnt_hash, &mnt->mnt_hash); | ||
802 | else | ||
803 | hlist_add_head_rcu(&mnt->mnt_hash, | ||
804 | m_hash(&parent->mnt, mnt->mnt_mountpoint)); | ||
805 | list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); | ||
806 | touch_mnt_namespace(n); | 814 | touch_mnt_namespace(n); |
807 | } | 815 | } |
808 | 816 | ||
@@ -890,8 +898,21 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
890 | 898 | ||
891 | mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED); | 899 | mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED); |
892 | /* Don't allow unprivileged users to change mount flags */ | 900 | /* Don't allow unprivileged users to change mount flags */ |
893 | if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY)) | 901 | if (flag & CL_UNPRIVILEGED) { |
894 | mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; | 902 | mnt->mnt.mnt_flags |= MNT_LOCK_ATIME; |
903 | |||
904 | if (mnt->mnt.mnt_flags & MNT_READONLY) | ||
905 | mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; | ||
906 | |||
907 | if (mnt->mnt.mnt_flags & MNT_NODEV) | ||
908 | mnt->mnt.mnt_flags |= MNT_LOCK_NODEV; | ||
909 | |||
910 | if (mnt->mnt.mnt_flags & MNT_NOSUID) | ||
911 | mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID; | ||
912 | |||
913 | if (mnt->mnt.mnt_flags & MNT_NOEXEC) | ||
914 | mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC; | ||
915 | } | ||
895 | 916 | ||
896 | /* Don't allow unprivileged users to reveal what is under a mount */ | 917 | /* Don't allow unprivileged users to reveal what is under a mount */ |
897 | if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire)) | 918 | if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire)) |
@@ -938,7 +959,6 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
938 | 959 | ||
939 | static void mntput_no_expire(struct mount *mnt) | 960 | static void mntput_no_expire(struct mount *mnt) |
940 | { | 961 | { |
941 | put_again: | ||
942 | rcu_read_lock(); | 962 | rcu_read_lock(); |
943 | mnt_add_count(mnt, -1); | 963 | mnt_add_count(mnt, -1); |
944 | if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */ | 964 | if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */ |
@@ -951,14 +971,6 @@ put_again: | |||
951 | unlock_mount_hash(); | 971 | unlock_mount_hash(); |
952 | return; | 972 | return; |
953 | } | 973 | } |
954 | if (unlikely(mnt->mnt_pinned)) { | ||
955 | mnt_add_count(mnt, mnt->mnt_pinned + 1); | ||
956 | mnt->mnt_pinned = 0; | ||
957 | rcu_read_unlock(); | ||
958 | unlock_mount_hash(); | ||
959 | acct_auto_close_mnt(&mnt->mnt); | ||
960 | goto put_again; | ||
961 | } | ||
962 | if (unlikely(mnt->mnt.mnt_flags & MNT_DOOMED)) { | 974 | if (unlikely(mnt->mnt.mnt_flags & MNT_DOOMED)) { |
963 | rcu_read_unlock(); | 975 | rcu_read_unlock(); |
964 | unlock_mount_hash(); | 976 | unlock_mount_hash(); |
@@ -981,6 +993,8 @@ put_again: | |||
981 | * so mnt_get_writers() below is safe. | 993 | * so mnt_get_writers() below is safe. |
982 | */ | 994 | */ |
983 | WARN_ON(mnt_get_writers(mnt)); | 995 | WARN_ON(mnt_get_writers(mnt)); |
996 | if (unlikely(mnt->mnt_pins.first)) | ||
997 | mnt_pin_kill(mnt); | ||
984 | fsnotify_vfsmount_delete(&mnt->mnt); | 998 | fsnotify_vfsmount_delete(&mnt->mnt); |
985 | dput(mnt->mnt.mnt_root); | 999 | dput(mnt->mnt.mnt_root); |
986 | deactivate_super(mnt->mnt.mnt_sb); | 1000 | deactivate_super(mnt->mnt.mnt_sb); |
@@ -1008,25 +1022,15 @@ struct vfsmount *mntget(struct vfsmount *mnt) | |||
1008 | } | 1022 | } |
1009 | EXPORT_SYMBOL(mntget); | 1023 | EXPORT_SYMBOL(mntget); |
1010 | 1024 | ||
1011 | void mnt_pin(struct vfsmount *mnt) | 1025 | struct vfsmount *mnt_clone_internal(struct path *path) |
1012 | { | ||
1013 | lock_mount_hash(); | ||
1014 | real_mount(mnt)->mnt_pinned++; | ||
1015 | unlock_mount_hash(); | ||
1016 | } | ||
1017 | EXPORT_SYMBOL(mnt_pin); | ||
1018 | |||
1019 | void mnt_unpin(struct vfsmount *m) | ||
1020 | { | 1026 | { |
1021 | struct mount *mnt = real_mount(m); | 1027 | struct mount *p; |
1022 | lock_mount_hash(); | 1028 | p = clone_mnt(real_mount(path->mnt), path->dentry, CL_PRIVATE); |
1023 | if (mnt->mnt_pinned) { | 1029 | if (IS_ERR(p)) |
1024 | mnt_add_count(mnt, 1); | 1030 | return ERR_CAST(p); |
1025 | mnt->mnt_pinned--; | 1031 | p->mnt.mnt_flags |= MNT_INTERNAL; |
1026 | } | 1032 | return &p->mnt; |
1027 | unlock_mount_hash(); | ||
1028 | } | 1033 | } |
1029 | EXPORT_SYMBOL(mnt_unpin); | ||
1030 | 1034 | ||
1031 | static inline void mangle(struct seq_file *m, const char *s) | 1035 | static inline void mangle(struct seq_file *m, const char *s) |
1032 | { | 1036 | { |
@@ -1492,6 +1496,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, | |||
1492 | continue; | 1496 | continue; |
1493 | 1497 | ||
1494 | for (s = r; s; s = next_mnt(s, r)) { | 1498 | for (s = r; s; s = next_mnt(s, r)) { |
1499 | struct mount *t = NULL; | ||
1495 | if (!(flag & CL_COPY_UNBINDABLE) && | 1500 | if (!(flag & CL_COPY_UNBINDABLE) && |
1496 | IS_MNT_UNBINDABLE(s)) { | 1501 | IS_MNT_UNBINDABLE(s)) { |
1497 | s = skip_mnt_tree(s); | 1502 | s = skip_mnt_tree(s); |
@@ -1513,7 +1518,14 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, | |||
1513 | goto out; | 1518 | goto out; |
1514 | lock_mount_hash(); | 1519 | lock_mount_hash(); |
1515 | list_add_tail(&q->mnt_list, &res->mnt_list); | 1520 | list_add_tail(&q->mnt_list, &res->mnt_list); |
1516 | attach_mnt(q, parent, p->mnt_mp); | 1521 | mnt_set_mountpoint(parent, p->mnt_mp, q); |
1522 | if (!list_empty(&parent->mnt_mounts)) { | ||
1523 | t = list_last_entry(&parent->mnt_mounts, | ||
1524 | struct mount, mnt_child); | ||
1525 | if (t->mnt_mp != p->mnt_mp) | ||
1526 | t = NULL; | ||
1527 | } | ||
1528 | attach_shadowed(q, parent, t); | ||
1517 | unlock_mount_hash(); | 1529 | unlock_mount_hash(); |
1518 | } | 1530 | } |
1519 | } | 1531 | } |
@@ -1896,9 +1908,6 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags) | |||
1896 | if (readonly_request == __mnt_is_readonly(mnt)) | 1908 | if (readonly_request == __mnt_is_readonly(mnt)) |
1897 | return 0; | 1909 | return 0; |
1898 | 1910 | ||
1899 | if (mnt->mnt_flags & MNT_LOCK_READONLY) | ||
1900 | return -EPERM; | ||
1901 | |||
1902 | if (readonly_request) | 1911 | if (readonly_request) |
1903 | error = mnt_make_readonly(real_mount(mnt)); | 1912 | error = mnt_make_readonly(real_mount(mnt)); |
1904 | else | 1913 | else |
@@ -1924,6 +1933,33 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
1924 | if (path->dentry != path->mnt->mnt_root) | 1933 | if (path->dentry != path->mnt->mnt_root) |
1925 | return -EINVAL; | 1934 | return -EINVAL; |
1926 | 1935 | ||
1936 | /* Don't allow changing of locked mnt flags. | ||
1937 | * | ||
1938 | * No locks need to be held here while testing the various | ||
1939 | * MNT_LOCK flags because those flags can never be cleared | ||
1940 | * once they are set. | ||
1941 | */ | ||
1942 | if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) && | ||
1943 | !(mnt_flags & MNT_READONLY)) { | ||
1944 | return -EPERM; | ||
1945 | } | ||
1946 | if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) && | ||
1947 | !(mnt_flags & MNT_NODEV)) { | ||
1948 | return -EPERM; | ||
1949 | } | ||
1950 | if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) && | ||
1951 | !(mnt_flags & MNT_NOSUID)) { | ||
1952 | return -EPERM; | ||
1953 | } | ||
1954 | if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) && | ||
1955 | !(mnt_flags & MNT_NOEXEC)) { | ||
1956 | return -EPERM; | ||
1957 | } | ||
1958 | if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) && | ||
1959 | ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) { | ||
1960 | return -EPERM; | ||
1961 | } | ||
1962 | |||
1927 | err = security_sb_remount(sb, data); | 1963 | err = security_sb_remount(sb, data); |
1928 | if (err) | 1964 | if (err) |
1929 | return err; | 1965 | return err; |
@@ -1937,7 +1973,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
1937 | err = do_remount_sb(sb, flags, data, 0); | 1973 | err = do_remount_sb(sb, flags, data, 0); |
1938 | if (!err) { | 1974 | if (!err) { |
1939 | lock_mount_hash(); | 1975 | lock_mount_hash(); |
1940 | mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; | 1976 | mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK; |
1941 | mnt->mnt.mnt_flags = mnt_flags; | 1977 | mnt->mnt.mnt_flags = mnt_flags; |
1942 | touch_mnt_namespace(mnt->mnt_ns); | 1978 | touch_mnt_namespace(mnt->mnt_ns); |
1943 | unlock_mount_hash(); | 1979 | unlock_mount_hash(); |
@@ -2122,7 +2158,7 @@ static int do_new_mount(struct path *path, const char *fstype, int flags, | |||
2122 | */ | 2158 | */ |
2123 | if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) { | 2159 | if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) { |
2124 | flags |= MS_NODEV; | 2160 | flags |= MS_NODEV; |
2125 | mnt_flags |= MNT_NODEV; | 2161 | mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV; |
2126 | } | 2162 | } |
2127 | } | 2163 | } |
2128 | 2164 | ||
@@ -2436,6 +2472,14 @@ long do_mount(const char *dev_name, const char *dir_name, | |||
2436 | if (flags & MS_RDONLY) | 2472 | if (flags & MS_RDONLY) |
2437 | mnt_flags |= MNT_READONLY; | 2473 | mnt_flags |= MNT_READONLY; |
2438 | 2474 | ||
2475 | /* The default atime for remount is preservation */ | ||
2476 | if ((flags & MS_REMOUNT) && | ||
2477 | ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME | | ||
2478 | MS_STRICTATIME)) == 0)) { | ||
2479 | mnt_flags &= ~MNT_ATIME_MASK; | ||
2480 | mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK; | ||
2481 | } | ||
2482 | |||
2439 | flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | | 2483 | flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | |
2440 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | | 2484 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | |
2441 | MS_STRICTATIME); | 2485 | MS_STRICTATIME); |
@@ -2972,13 +3016,13 @@ static void *mntns_get(struct task_struct *task) | |||
2972 | struct mnt_namespace *ns = NULL; | 3016 | struct mnt_namespace *ns = NULL; |
2973 | struct nsproxy *nsproxy; | 3017 | struct nsproxy *nsproxy; |
2974 | 3018 | ||
2975 | rcu_read_lock(); | 3019 | task_lock(task); |
2976 | nsproxy = task_nsproxy(task); | 3020 | nsproxy = task->nsproxy; |
2977 | if (nsproxy) { | 3021 | if (nsproxy) { |
2978 | ns = nsproxy->mnt_ns; | 3022 | ns = nsproxy->mnt_ns; |
2979 | get_mnt_ns(ns); | 3023 | get_mnt_ns(ns); |
2980 | } | 3024 | } |
2981 | rcu_read_unlock(); | 3025 | task_unlock(task); |
2982 | 3026 | ||
2983 | return ns; | 3027 | return ns; |
2984 | } | 3028 | } |