--- /dev/null
+diff --git a/fs/wrapfs/inode.c b/fs/wrapfs/inode.c
+index ab0aff1abbd9..0eb68b3e3e25 100644
+--- a/fs/wrapfs/inode.c
++++ b/fs/wrapfs/inode.c
+@@ -8,7 +8,8 @@
+
+ #include "wrapfs.h"
+
+-static int wrapfs_create(struct inode *dir, struct dentry *dentry,
++static int wrapfs_create(struct user_namespace *mnt_userns,
++ struct inode *dir, struct dentry *dentry,
+ umode_t mode, bool want_excl)
+ {
+ int err;
+@@ -20,7 +21,8 @@ static int wrapfs_create(struct inode *dir, struct dentry *dentry,
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_create(d_inode(lower_parent_dentry), lower_dentry, mode,
++ err = vfs_create(&init_user_ns, d_inode(lower_parent_dentry),
++ lower_dentry, mode,
+ want_excl);
+ if (err)
+ goto out;
+@@ -53,8 +55,8 @@ static int wrapfs_link(struct dentry *old_dentry, struct inode *dir,
+ lower_new_dentry = lower_new_path.dentry;
+ lower_dir_dentry = lock_parent(lower_new_dentry);
+
+- err = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry),
+- lower_new_dentry, NULL);
++ err = vfs_link(lower_old_dentry, &init_user_ns,
++ d_inode(lower_dir_dentry), lower_new_dentry, NULL);
+ if (err || d_really_is_negative(lower_new_dentry))
+ goto out;
+
+@@ -91,7 +93,8 @@ static int wrapfs_unlink(struct inode *dir, struct dentry *dentry)
+ goto out;
+ }
+
+- err = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
++ err = vfs_unlink(&init_user_ns, lower_dir_inode, lower_dentry,
++ NULL);
+
+ /*
+ * Note: unlinking on top of NFS can cause silly-renamed files.
+@@ -117,7 +120,8 @@ static int wrapfs_unlink(struct inode *dir, struct dentry *dentry)
+ return err;
+ }
+
+-static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
++static int wrapfs_symlink(struct user_namespace *mnt_userns,
++ struct inode *dir, struct dentry *dentry,
+ const char *symname)
+ {
+ int err;
+@@ -129,7 +133,8 @@ static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_symlink(d_inode(lower_parent_dentry), lower_dentry, symname);
++ err = vfs_symlink(&init_user_ns, d_inode(lower_parent_dentry),
++ lower_dentry, symname);
+ if (err)
+ goto out;
+ err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
+@@ -144,7 +149,8 @@ static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
+ return err;
+ }
+
+-static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++static int wrapfs_mkdir(struct user_namespace *mnt_userns,
++ struct inode *dir, struct dentry *dentry, umode_t mode)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -155,7 +161,8 @@ static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_mkdir(d_inode(lower_parent_dentry), lower_dentry, mode);
++ err = vfs_mkdir(&init_user_ns, d_inode(lower_parent_dentry),
++ lower_dentry, mode);
+ if (err)
+ goto out;
+
+@@ -190,7 +197,8 @@ static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry)
+ goto out;
+ }
+
+- err = vfs_rmdir(d_inode(lower_dir_dentry), lower_dentry);
++ err = vfs_rmdir(&init_user_ns, d_inode(lower_dir_dentry),
++ lower_dentry);
+ if (err)
+ goto out;
+
+@@ -207,8 +215,8 @@ static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry)
+ return err;
+ }
+
+-static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+- dev_t dev)
++static int wrapfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
++ struct dentry *dentry, umode_t mode, dev_t dev)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -219,7 +227,8 @@ static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+ lower_dentry = lower_path.dentry;
+ lower_parent_dentry = lock_parent(lower_dentry);
+
+- err = vfs_mknod(d_inode(lower_parent_dentry), lower_dentry, mode, dev);
++ err = vfs_mknod(&init_user_ns, d_inode(lower_parent_dentry),
++ lower_dentry, mode, dev);
+ if (err)
+ goto out;
+
+@@ -239,7 +248,8 @@ static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+ * The locking rules in wrapfs_rename are complex. We could use a simpler
+ * superblock-level name-space lock for renames and copy-ups.
+ */
+-static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
++static int wrapfs_rename(struct user_namespace *mnt_userns,
++ struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
+ {
+@@ -250,6 +260,7 @@ static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct dentry *lower_new_dir_dentry = NULL;
+ struct dentry *trap = NULL;
+ struct path lower_old_path, lower_new_path;
++ struct renamedata rd = {};
+
+ if (flags)
+ return -EINVAL;
+@@ -280,9 +291,13 @@ static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ goto out;
+ }
+
+- err = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry,
+- d_inode(lower_new_dir_dentry), lower_new_dentry,
+- NULL, 0);
++ rd.old_mnt_userns = &init_user_ns;
++ rd.old_dir = d_inode(lower_old_dir_dentry);
++ rd.old_dentry = lower_old_dentry;
++ rd.new_mnt_userns = &init_user_ns;
++ rd.new_dir = d_inode(lower_new_dir_dentry);
++ rd.new_dentry = lower_new_dentry;
++ err = vfs_rename(&rd);
+ if (err)
+ goto out;
+
+@@ -348,17 +363,19 @@ static const char *wrapfs_get_link(struct dentry *dentry, struct inode *inode,
+ return buf;
+ }
+
+-static int wrapfs_permission(struct inode *inode, int mask)
++static int wrapfs_permission(struct user_namespace *mnt_userns,
++ struct inode *inode, int mask)
+ {
+ struct inode *lower_inode;
+ int err;
+
+ lower_inode = wrapfs_lower_inode(inode);
+- err = inode_permission(lower_inode, mask);
++ err = inode_permission(&init_user_ns, lower_inode, mask);
+ return err;
+ }
+
+-static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
++static int wrapfs_setattr(struct user_namespace *mnt_userns,
++ struct dentry *dentry, struct iattr *ia)
+ {
+ int err;
+ struct dentry *lower_dentry;
+@@ -374,7 +391,7 @@ static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
+ * this user can change the lower inode: that should happen when
+ * calling notify_change on the lower inode.
+ */
+- err = setattr_prepare(dentry, ia);
++ err = setattr_prepare(&init_user_ns, dentry, ia);
+ if (err)
+ goto out_err;
+
+@@ -416,8 +433,7 @@ static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
+ * tries to open(), unlink(), then ftruncate() a file.
+ */
+ inode_lock(d_inode(lower_dentry));
+- err = notify_change(lower_dentry, &lower_ia, /* note: lower_ia */
+- NULL);
++ err = notify_change(&init_user_ns, lower_dentry, &lower_ia, NULL);
+ inode_unlock(d_inode(lower_dentry));
+ if (err)
+ goto out;
+@@ -436,7 +452,8 @@ static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
+ return err;
+ }
+
+-static int wrapfs_getattr(const struct path *path, struct kstat *stat,
++static int wrapfs_getattr(struct user_namespace *mnt_userns,
++ const struct path *path, struct kstat *stat,
+ u32 request_mask, unsigned int flags)
+ {
+ int err;
+@@ -450,7 +467,7 @@ static int wrapfs_getattr(const struct path *path, struct kstat *stat,
+ goto out;
+ fsstack_copy_attr_all(d_inode(dentry),
+ d_inode(lower_path.dentry));
+- generic_fillattr(d_inode(dentry), stat);
++ generic_fillattr(&init_user_ns, d_inode(dentry), stat);
+ stat->blocks = lower_stat.blocks;
+ out:
+ wrapfs_put_lower_path(dentry, &lower_path);
+@@ -470,7 +487,7 @@ wrapfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+- err = vfs_setxattr(lower_dentry, name, value, size, flags);
++ err = vfs_setxattr(&init_user_ns, lower_dentry, name, value, size, flags);
+ if (err)
+ goto out;
+ fsstack_copy_attr_all(d_inode(dentry),
+@@ -496,7 +513,7 @@ wrapfs_getxattr(struct dentry *dentry, struct inode *inode,
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+- err = vfs_getxattr(lower_dentry, name, buffer, size);
++ err = vfs_getxattr(&init_user_ns, lower_dentry, name, buffer, size);
+ if (err)
+ goto out;
+ fsstack_copy_attr_atime(d_inode(dentry),
+@@ -544,7 +561,7 @@ wrapfs_removexattr(struct dentry *dentry, struct inode *inode, const char *name)
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+- err = vfs_removexattr(lower_dentry, name);
++ err = vfs_removexattr(&init_user_ns, lower_dentry, name);
+ if (err)
+ goto out;
+ fsstack_copy_attr_all(d_inode(dentry), lower_inode);
+@@ -592,6 +609,7 @@ static int wrapfs_xattr_get(const struct xattr_handler *handler,
+ }
+
+ static int wrapfs_xattr_set(const struct xattr_handler *handler,
++ struct user_namespace *mnt_userns,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size,
+ int flags)
+diff --git a/fs/wrapfs/main.c b/fs/wrapfs/main.c
+index 3df02cc778b3..15c97a78d765 100644
+--- a/fs/wrapfs/main.c
++++ b/fs/wrapfs/main.c
+@@ -9,6 +9,8 @@
+ #include "wrapfs.h"
+ #include <linux/module.h>
+
++static struct file_system_type wrapfs_fs_type;
++
+ /*
+ * There is no need to lock the wrapfs_super_info's rwsem as there is no
+ * way anyone can have a reference to the superblock at this point in time.
+@@ -37,6 +39,21 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent)
+ goto out;
+ }
+
++ if (lower_path.dentry->d_sb->s_type == &wrapfs_fs_type) {
++ err = -EINVAL;
++ printk(KERN_ERR "Mount on filesystem of type "
++ "wrapfs explicitly disallowed due to "
++ "known incompatibilities\n");
++ goto out_pput;
++ }
++
++ if (mnt_user_ns(lower_path.mnt) != &init_user_ns) {
++ err = -EINVAL;
++ printk(KERN_ERR "Mounting on idmapped mounts currently "
++ "disallowed\n");
++ goto out_pput;
++ }
++
+ /* allocate superblock private data */
+ sb->s_fs_info = kzalloc(sizeof(struct wrapfs_sb_info), GFP_KERNEL);
+ if (!WRAPFS_SB(sb)) {
+diff --git a/fs/wrapfs/mmap.c b/fs/wrapfs/mmap.c
+index 9897fa585b97..d3ae80c9ded1 100644
+--- a/fs/wrapfs/mmap.c
++++ b/fs/wrapfs/mmap.c
+@@ -15,6 +15,7 @@ static vm_fault_t wrapfs_fault(struct vm_fault *vmf)
+ struct file *file, *lower_file;
+ const struct vm_operations_struct *lower_vm_ops;
+ struct vm_area_struct lower_vma;
++ struct vm_area_struct **vma_p = (struct vm_area_struct**) &vmf->vma;
+
+ memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
+ file = lower_vma.vm_file;
+@@ -33,9 +34,9 @@ static vm_fault_t wrapfs_fault(struct vm_fault *vmf)
+ * take an explicit file pointer.
+ */
+ lower_vma.vm_file = lower_file;
+- vmf->vma = &lower_vma; /* override vma temporarily */
++ *vma_p = &lower_vma; /* override vma temporarily */
+ err = lower_vm_ops->fault(vmf);
+- vmf->vma = vma; /* restore vma*/
++ *vma_p = vma; /* restore vma */
+ return err;
+ }
+
+@@ -46,6 +47,7 @@ static vm_fault_t wrapfs_page_mkwrite(struct vm_fault *vmf)
+ struct file *file, *lower_file;
+ const struct vm_operations_struct *lower_vm_ops;
+ struct vm_area_struct lower_vma;
++ struct vm_area_struct **vma_p = (struct vm_area_struct**) &vmf->vma;
+
+ memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
+ file = lower_vma.vm_file;
+@@ -67,9 +69,9 @@ static vm_fault_t wrapfs_page_mkwrite(struct vm_fault *vmf)
+ * ->page_mkwrite to take an explicit file pointer.
+ */
+ lower_vma.vm_file = lower_file;
+- vmf->vma = &lower_vma; /* override vma temporarily */
++ *vma_p = &lower_vma; /* override vma temporarily */
+ err = lower_vm_ops->page_mkwrite(vmf);
+- vmf->vma = vma; /* restore vma */
++ *vma_p = vma; /* restore vma */
+ out:
+ return err;
+ }