diff --git a/fs/namespace.c b/fs/namespace.c
index 9d1374ab6e06..0d466885c181 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2489,7 +2489,7 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
 	return err;
 }
 
-static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags);
+static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags, int *hideable_categories);
 
 /*
  * create a new mount for userspace and request it to be added into the
@@ -2500,6 +2500,7 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
 {
 	struct file_system_type *type;
 	struct vfsmount *mnt;
+	int hideable_categories = 0;
 	int err;
 
 	if (!fstype)
@@ -2518,11 +2519,15 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
 	if (IS_ERR(mnt))
 		return PTR_ERR(mnt);
 
-	if (mount_too_revealing(mnt, &mnt_flags)) {
+	if (mount_too_revealing(mnt, &mnt_flags, &hideable_categories)) {
 		mntput(mnt);
 		return -EPERM;
 	}
 
+	if (hideable_categories != 0) {
+		/* TODO: configure the mount to hide the categories of files */
+	}
+
 	err = do_add_mount(real_mount(mnt), path, mnt_flags);
 	if (err)
 		mntput(mnt);
@@ -3342,7 +3347,7 @@ bool current_chrooted(void)
 }
 
 static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
-				int *new_mnt_flags)
+				int *new_mnt_flags, int *hideable_categories)
 {
 	int new_flags = *new_mnt_flags;
 	struct mount *mnt;
@@ -3352,6 +3357,7 @@ static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
 	list_for_each_entry(mnt, &ns->list, mnt_list) {
 		struct mount *child;
 		int mnt_flags;
+		int local_hideable_categories = 0;
 
 		if (mnt->mnt.mnt_sb->s_type != new->mnt_sb->s_type)
 			continue;
@@ -3388,6 +3394,12 @@ static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
 			/* Only worry about locked mounts */
 			if (!(child->mnt.mnt_flags & MNT_LOCKED))
 				continue;
+			/* Hideable inodes might be ok but gather categories */
+			if (inode->i_opflags & IOP_USERNS_HIDEABLE) {
+				/* TODO: get proc_dir_entry->userns_hideable_categories */
+				local_hideable_categories |= 0x01;
+				continue;
+			}
 			/* Is the directory permanetly empty? */
 			if (!is_empty_dir_inode(inode))
 				goto next;
@@ -3395,6 +3407,10 @@ static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
 		/* Preserve the locked attributes */
 		*new_mnt_flags |= mnt_flags & (MNT_LOCK_READONLY | \
 					       MNT_LOCK_ATIME);
+		/* Preserve hidden categories */
+		*hideable_categories |= local_hideable_categories;
+		/* TODO: for nested containers */
+		*hideable_categories |= 0; /* proc_sb(mnt->mnt.mnt_sb)->hideable_categories */
 		visible = true;
 		goto found;
 	next:	;
@@ -3404,7 +3420,7 @@ static bool mnt_already_visible(struct mnt_namespace *ns, struct vfsmount *new,
 	return visible;
 }
 
-static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
+static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags, int *hideable_categories)
 {
 	const unsigned long required_iflags = SB_I_NOEXEC | SB_I_NODEV;
 	struct mnt_namespace *ns = current->nsproxy->mnt_ns;
@@ -3424,7 +3440,7 @@ static bool mount_too_revealing(struct vfsmount *mnt, int *new_mnt_flags)
 		return true;
 	}
 
-	return !mnt_already_visible(ns, mnt, new_mnt_flags);
+	return !mnt_already_visible(ns, mnt, new_mnt_flags, hideable_categories);
 }
 
 bool mnt_may_suid(struct vfsmount *mnt)
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 5d709fa8f3a2..96537a0f751e 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -491,6 +491,11 @@ struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
 	pde->proc_fops = proc_fops;
 	pde->data = data;
 	pde->proc_iops = &proc_file_inode_operations;
+
+	// TODO: add parameters to proc_create() instead of hardcoding
+	if (strcmp(name, "kcore") == 0)
+		pde->userns_hideable = true;
+
 	if (proc_register(parent, pde) < 0)
 		goto out_free;
 	return pde;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 6e8724958116..dbf8f2dfe85e 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -455,6 +455,8 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
 			set_nlink(inode, de->nlink);
 		WARN_ON(!de->proc_iops);
 		inode->i_op = de->proc_iops;
+		if (de->userns_hideable)
+			inode->i_opflags |= IOP_USERNS_HIDEABLE;
 		if (de->proc_fops) {
 			if (S_ISREG(inode->i_mode)) {
 #ifdef CONFIG_COMPAT
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index d697c8ab0a14..7176fbff3660 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -52,6 +52,7 @@ struct proc_dir_entry {
 	struct proc_dir_entry *parent;
 	struct rb_root_cached subdir;
 	struct rb_node subdir_node;
+	bool userns_hideable;
 	umode_t mode;
 	u8 namelen;
 	char name[];
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c6baf767619e..4203c4d3330f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -559,6 +559,7 @@ is_uncached_acl(struct posix_acl *acl)
 #define IOP_NOFOLLOW	0x0004
 #define IOP_XATTR	0x0008
 #define IOP_DEFAULT_READLINK	0x0010
+#define IOP_USERNS_HIDEABLE	0x0020
 
 struct fsnotify_mark_connector;
 
