···1013101310141014 mnt->mnt.mnt_flags = old->mnt.mnt_flags;10151015 mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL);10161016- /* Don't allow unprivileged users to change mount flags */10171017- if (flag & CL_UNPRIVILEGED) {10181018- mnt->mnt.mnt_flags |= MNT_LOCK_ATIME;10191019-10201020- if (mnt->mnt.mnt_flags & MNT_READONLY)10211021- mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;10221022-10231023- if (mnt->mnt.mnt_flags & MNT_NODEV)10241024- mnt->mnt.mnt_flags |= MNT_LOCK_NODEV;10251025-10261026- if (mnt->mnt.mnt_flags & MNT_NOSUID)10271027- mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID;10281028-10291029- if (mnt->mnt.mnt_flags & MNT_NOEXEC)10301030- mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC;10311031- }10321032-10331033- /* Don't allow unprivileged users to reveal what is under a mount */10341034- if ((flag & CL_UNPRIVILEGED) &&10351035- (!(flag & CL_EXPIRE) || list_empty(&old->mnt_expire)))10361036- mnt->mnt.mnt_flags |= MNT_LOCKED;1037101610381017 atomic_inc(&sb->s_active);10391018 mnt->mnt.mnt_sb = sb;···18161837 return 0;18171838}1818183918401840+static void lock_mnt_tree(struct mount *mnt)18411841+{18421842+ struct mount *p;18431843+18441844+ for (p = mnt; p; p = next_mnt(p, mnt)) {18451845+ int flags = p->mnt.mnt_flags;18461846+ /* Don't allow unprivileged users to change mount flags */18471847+ flags |= MNT_LOCK_ATIME;18481848+18491849+ if (flags & MNT_READONLY)18501850+ flags |= MNT_LOCK_READONLY;18511851+18521852+ if (flags & MNT_NODEV)18531853+ flags |= MNT_LOCK_NODEV;18541854+18551855+ if (flags & MNT_NOSUID)18561856+ flags |= MNT_LOCK_NOSUID;18571857+18581858+ if (flags & MNT_NOEXEC)18591859+ flags |= MNT_LOCK_NOEXEC;18601860+ /* Don't allow unprivileged users to reveal what is under a mount */18611861+ if (list_empty(&p->mnt_expire))18621862+ flags |= MNT_LOCKED;18631863+ p->mnt.mnt_flags = flags;18641864+ }18651865+}18661866+18191867static void cleanup_group_ids(struct mount *mnt, struct mount *end)18201868{18211869 struct mount *p;···19601954 struct mountpoint *dest_mp,19611955 struct path *parent_path)19621956{19571957+ struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;19631958 HLIST_HEAD(tree_list);19641959 struct mnt_namespace *ns = dest_mnt->mnt_ns;19651960 struct mountpoint *smp;···20112004 child->mnt_mountpoint);20122005 if (q)20132006 mnt_change_mountpoint(child, smp, q);20072007+ /* Notice when we are propagating across user namespaces */20082008+ if (child->mnt_parent->mnt_ns->user_ns != user_ns)20092009+ lock_mnt_tree(child);20142010 commit_tree(child);20152011 }20162012 put_mountpoint(smp);···29512941 /* First pass: copy the tree topology */29522942 copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE;29532943 if (user_ns != ns->user_ns)29542954- copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;29442944+ copy_flags |= CL_SHARED_TO_SLAVE;29552945 new = copy_tree(old, old->mnt.mnt_root, copy_flags);29562946 if (IS_ERR(new)) {29572947 namespace_unlock();29582948 free_mnt_ns(new_ns);29592949 return ERR_CAST(new);29502950+ }29512951+ if (user_ns != ns->user_ns) {29522952+ lock_mount_hash();29532953+ lock_mnt_tree(new);29542954+ unlock_mount_hash();29602955 }29612956 new_ns->root = new;29622957 list_add_tail(&new_ns->list, &new->mnt_list);
-5
fs/pnode.c
···214214}215215216216/* all accesses are serialized by namespace_sem */217217-static struct user_namespace *user_ns;218217static struct mount *last_dest, *first_source, *last_source, *dest_master;219218static struct mountpoint *mp;220219static struct hlist_head *list;···259260 type |= CL_MAKE_SHARED;260261 }261262262262- /* Notice when we are propagating across user namespaces */263263- if (m->mnt_ns->user_ns != user_ns)264264- type |= CL_UNPRIVILEGED;265263 child = copy_tree(last_source, last_source->mnt.mnt_root, type);266264 if (IS_ERR(child))267265 return PTR_ERR(child);···299303 * propagate_one(); everything is serialized by namespace_sem,300304 * so globals will do just fine.301305 */302302- user_ns = current->nsproxy->mnt_ns->user_ns;303306 last_dest = dest_mnt;304307 first_source = source_mnt;305308 last_source = source_mnt;