diff --git a/include/linux/ima.h b/include/linux/ima.h
index b6ab66a546ae..3391567b661e 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -13,6 +13,7 @@
 #include <linux/kexec.h>
 #include <crypto/hash_info.h>
 struct linux_binprm;
+struct ima_ns_info;
 
 #ifdef CONFIG_IMA
 extern enum hash_algo ima_get_current_hash_algo(void);
@@ -39,7 +40,8 @@ extern int ima_measure_critical_data(const char *event_label,
 				     const char *event_name,
 				     const void *buf, size_t buf_len,
 				     bool hash, u8 *digest, size_t digest_len);
-
+extern void ima_init_user_ns(struct user_namespace *ns);
+extern void ima_free_user_ns(struct user_namespace *ns);
 #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
 extern void ima_appraise_parse_cmdline(void);
 #else
@@ -153,6 +155,16 @@ static inline int ima_measure_critical_data(const char *event_label,
 	return -ENOENT;
 }
 
+static inline void ima_init_user_ns(struct user_namespace *ns)
+{
+	return;
+}
+
+static inline void ima_free_user_ns(struct user_namespace *ns)
+{
+	return;
+}
+
 #endif /* CONFIG_IMA */
 
 #ifndef CONFIG_IMA_KEXEC
diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h
index 33a4240e6a6f..88d2a39596ba 100644
--- a/include/linux/user_namespace.h
+++ b/include/linux/user_namespace.h
@@ -2,6 +2,7 @@
 #ifndef _LINUX_USER_NAMESPACE_H
 #define _LINUX_USER_NAMESPACE_H
 
+#include <linux/ima.h>
 #include <linux/kref.h>
 #include <linux/nsproxy.h>
 #include <linux/ns_common.h>
@@ -99,6 +100,9 @@ struct user_namespace {
 #endif
 	struct ucounts		*ucounts;
 	long ucount_max[UCOUNT_COUNTS];
+#ifdef CONFIG_IMA
+	struct ima_ns_info	*ima_ns_info;
+#endif
 } __randomize_layout;
 
 struct ucounts {
diff --git a/kernel/user.c b/kernel/user.c
index e2cf8c22b539..40c0fb44ecad 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -67,6 +67,7 @@ struct user_namespace init_user_ns = {
 	.keyring_name_list = LIST_HEAD_INIT(init_user_ns.keyring_name_list),
 	.keyring_sem = __RWSEM_INITIALIZER(init_user_ns.keyring_sem),
 #endif
+	/* ima_ns_info is initialized in user_namespaces_init() */
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 6b2e3ca7ee99..08b6aaf0382b 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
 #include <linux/export.h>
+#include <linux/ima.h>
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 #include <linux/sched/signal.h>
@@ -142,6 +143,9 @@ int create_user_ns(struct cred *new)
 		goto fail_keyring;
 
 	set_cred_user_ns(new, ns);
+
+	ima_init_user_ns(ns);
+
 	return 0;
 fail_keyring:
 #ifdef CONFIG_PERSISTENT_KEYRINGS
@@ -198,6 +202,7 @@ static void free_user_ns(struct work_struct *work)
 		}
 		retire_userns_sysctls(ns);
 		key_free_user_ns(ns);
+		ima_free_user_ns(ns);
 		ns_free_inum(&ns->ns);
 		kmem_cache_free(user_ns_cachep, ns);
 		dec_user_namespaces(ucounts);
@@ -1386,6 +1391,7 @@ const struct proc_ns_operations userns_operations = {
 static __init int user_namespaces_init(void)
 {
 	user_ns_cachep = KMEM_CACHE(user_namespace, SLAB_PANIC | SLAB_ACCOUNT);
+	ima_init_user_ns(&init_user_ns);
 	return 0;
 }
 subsys_initcall(user_namespaces_init);
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 2499f2485c04..1741aa5d97bc 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -7,7 +7,7 @@
 obj-$(CONFIG_IMA) += ima.o
 
 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
-	 ima_policy.o ima_template.o ima_template_lib.o
+	 ima_policy.o ima_template.o ima_template_lib.o ima_ns.o
 ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
 ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
 ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index be965a8715e4..b3f90971a4f7 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -301,6 +301,14 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos);
 void ima_policy_stop(struct seq_file *m, void *v);
 int ima_policy_show(struct seq_file *m, void *v);
 
+/* IMA Namespace related functions */
+struct ima_ns_info {
+	char label[40];		/* UUIDs are 37 ascii characters */
+	struct list_head entry;
+};
+const char *ima_ns_info_get_label(struct user_namespace *ns);
+int ima_ns_info_set_label(struct user_namespace *ns, const char *label);
+
 /* Appraise integrity measurements */
 #define IMA_APPRAISE_ENFORCE	0x01
 #define IMA_APPRAISE_FIX	0x02
diff --git a/security/integrity/ima/ima_ns.c b/security/integrity/ima/ima_ns.c
new file mode 100644
index 000000000000..a0358806149b
--- /dev/null
+++ b/security/integrity/ima/ima_ns.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * IMA Namespace Support routines
+ */
+
+#include <linux/ima.h>
+#include <linux/mutex.h>
+#include <linux/user_namespace.h>
+
+#include "ima.h"
+
+static struct kmem_cache *ima_ns_info_cache __read_mostly;
+static DEFINE_MUTEX(ns_info_list_lock);
+static LIST_HEAD(ima_ns_info_list);
+
+int ima_ns_info_set_label(struct user_namespace *ns, const char *label)
+{
+	bool found;
+	struct ima_ns_info *entry;
+
+	if (ns->ima_ns_info->label[0] != '\0')
+		/* label is already set */
+		return -EINVAL;
+
+	if (strlen(label) >= sizeof(ns->ima_ns_info->label))
+		return -E2BIG;
+
+	mutex_lock(&ns_info_list_lock);
+	list_for_each_entry(entry, &ima_ns_info_list, entry) {
+		if (strcmp(entry->label, label) == 0) {
+			found = true;
+			break;
+		}
+	}
+	mutex_unlock(&ns_info_list_lock);
+	if (found)
+		return -EEXIST;
+
+	strcpy(ns->ima_ns_info->label, label);
+
+	return 0;
+}
+
+const char *ima_ns_info_get_label(struct user_namespace *ns)
+{
+	if (unlikely(ns->ima_ns_info->label[0] == '\0')) {
+		uuid_t uuid;
+
+		uuid_gen(&uuid);
+		sprintf(ns->ima_ns_info->label, "%pU", &uuid);
+	}
+	return ns->ima_ns_info->label;
+}
+
+void ima_init_user_ns(struct user_namespace *ns)
+{
+	struct ima_ns_info *insi;
+
+	if (unlikely(!ima_ns_info_cache))
+		ima_ns_info_cache = KMEM_CACHE(ima_ns_info, SLAB_PANIC);
+
+	insi = kmem_cache_zalloc(ima_ns_info_cache, GFP_KERNEL);
+	ns->ima_ns_info = insi;
+	INIT_LIST_HEAD(&insi->entry);
+	mutex_lock(&ns_info_list_lock);
+	list_add_tail(&insi->entry, &ima_ns_info_list);
+	mutex_unlock(&ns_info_list_lock);
+}
+
+void ima_free_user_ns(struct user_namespace *ns)
+{
+}
