diff --git a/Makefile.rhelver b/Makefile.rhelver index bdf98e3074..9a7274c2ad 100644 --- a/Makefile.rhelver +++ b/Makefile.rhelver @@ -12,7 +12,7 @@ RHEL_MINOR = 10 # # Use this spot to avoid future merge conflicts. # Do not trim this comment. -RHEL_RELEASE = 553.107.1 +RHEL_RELEASE = 553.109.1 # # ZSTREAM diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index ec6d8f74f2..4c72f5a1a7 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -27,6 +29,9 @@ #include #include #include +#include "../mount.h" +#include + /* This is the range of ioctl() numbers we claim as ours */ #define AUTOFS_IOC_FIRST AUTOFS_IOC_READY @@ -115,6 +120,7 @@ struct autofs_sb_info { int pipefd; struct file *pipe; struct pid *oz_pgrp; + u64 mnt_ns_id; int version; int sub_version; int min_proto; diff --git a/fs/autofs/dev-ioctl.c b/fs/autofs/dev-ioctl.c index cad300ff73..5dbe1ffade 100644 --- a/fs/autofs/dev-ioctl.c +++ b/fs/autofs/dev-ioctl.c @@ -382,6 +382,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, swap(sbi->oz_pgrp, new_pid); sbi->pipefd = pipefd; sbi->pipe = pipe; + sbi->mnt_ns_id = current->nsproxy->mnt_ns->seq; sbi->flags &= ~AUTOFS_SBI_CATATONIC; } out: diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 72c20540c0..4a930e029d 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -242,6 +242,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) s->s_fs_info = sbi; sbi->magic = AUTOFS_SBI_MAGIC; sbi->pipefd = -1; + sbi->mnt_ns_id = current->nsproxy->mnt_ns->seq; sbi->pipe = NULL; sbi->exp_timeout = 0; sbi->oz_pgrp = NULL; diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 1246f396bf..68997b1d00 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -345,6 +345,14 @@ static struct vfsmount *autofs_d_automount(struct path *path) if (autofs_oz_mode(sbi)) return NULL; + /* Refuse to trigger mount if current namespace is not the owner + * and the mount is propagation private. + */ + if (sbi->mnt_ns_id != current->nsproxy->mnt_ns->seq) { + if (vfsmount_to_propagation_flags(path->mnt) & MS_PRIVATE) + return ERR_PTR(-EPERM); + } + /* * If an expire request is pending everyone must wait. * If the expire fails we're still mounted so continue diff --git a/fs/namespace.c b/fs/namespace.c index be37d60995..5fa6f0a8d1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3759,6 +3759,27 @@ out0: return error; } +static u64 mnt_to_propagation_flags(struct mount *m) +{ + u64 propagation = 0; + + if (IS_MNT_SHARED(m)) + propagation |= MS_SHARED; + if (IS_MNT_SLAVE(m)) + propagation |= MS_SLAVE; + if (IS_MNT_UNBINDABLE(m)) + propagation |= MS_UNBINDABLE; + if (!propagation) + propagation |= MS_PRIVATE; + + return propagation; +} + +u64 vfsmount_to_propagation_flags(struct vfsmount *mnt) +{ + return mnt_to_propagation_flags(real_mount(mnt)); +} + static void __init init_mount_tree(void) { struct vfsmount *mnt; diff --git a/include/linux/fs.h b/include/linux/fs.h index 8aae96b246..7f7a0ab852 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2994,6 +2994,7 @@ extern struct file * open_exec(const char *); /* fs/dcache.c -- generic fs support functions */ extern bool is_subdir(struct dentry *, struct dentry *); extern bool path_is_under(const struct path *, const struct path *); +u64 vfsmount_to_propagation_flags(struct vfsmount *mnt); extern char *file_path(struct file *, char *, int); diff --git a/mm/migrate.c b/mm/migrate.c index fe8444fd7b..ff5bffc90a 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1298,6 +1298,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, struct page *new_hpage; struct anon_vma *anon_vma = NULL; struct address_space *mapping = NULL; + enum ttu_flags ttu = TTU_MIGRATION|TTU_IGNORE_MLOCK; /* * Migratability of hugepages depends on architectures and their size. @@ -1345,9 +1346,6 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, goto put_anon; if (page_mapped(hpage)) { - bool mapping_locked = false; - enum ttu_flags ttu = TTU_MIGRATION|TTU_IGNORE_MLOCK; - if (!PageAnon(hpage)) { /* * In shared mappings, try_to_unmap could potentially @@ -1359,15 +1357,11 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, if (unlikely(!mapping)) goto unlock_put_anon; - mapping_locked = true; ttu |= TTU_RMAP_LOCKED; } try_to_unmap(hpage, ttu); page_was_mapped = 1; - - if (mapping_locked) - i_mmap_unlock_write(mapping); } if (!page_mapped(hpage)) @@ -1375,7 +1369,11 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, if (page_was_mapped) remove_migration_ptes(hpage, - rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage, false); + rc == MIGRATEPAGE_SUCCESS ? new_hpage : hpage, + (ttu & TTU_RMAP_LOCKED) ? true : false); + + if (ttu & TTU_RMAP_LOCKED) + i_mmap_unlock_write(mapping); unlock_put_anon: unlock_page(new_hpage);