diff mbox series

[RFC,2/3] ima: Namespace IMA

Message ID 20211127164549.2571457-3-James.Bottomley@HansenPartnership.com (mailing list archive)
State New, archived
Headers show
Series Namespace IMA | expand

Commit Message

James Bottomley Nov. 27, 2021, 4:45 p.m. UTC
Use the user namespace as the basis for namespacing IMA.  The
implementation is very simple: add a new template called 'ima-ns'
which exports the uuid of the user namespace into the IMA log.  This
can be used to uniquely separate every container in the IMA log.

Note that the admin of the user namespace still cannot read back the
IMA log because the IMA securityfs entries are not yet namespace
aware.  However, root in the init_user_ns can read the log and see the
containers.

You can get the uuid of init_user_ns from the boot_aggregate entry
which is always the first one recorded in the log.  Any execution with
a different uuid is in a new IMA namespace.

A sample of the log showing entry into a container is:

10 7766c926c9db8dd4c923f96be5635b04593029c1 ima-ns sha256:0000000000000000000000000000000000000000000000000000000000000000 boot_aggregate 6582e360-1354-42b9-a6ef-ee1993d982da
[...]
10 e0355132472d4d0ae1cc044412b4033bd5e1a48a ima-ns sha256:353e4d6b807056757fb5df31bafe7df80605bec20b445d5e9afd949ca4147d49 /usr/bin/unshare 6582e360-1354-42b9-a6ef-ee1993d982da
10 f257f5a12fd6e28d32b367a2e453c3badd0e8774 ima-ns sha256:2a7c66fc7e19acc100ee2b777b71179043fade8b81968828522cf31e6a96eaa7 /usr/bin/bash e496e384-4133-4d57-b93a-1812b83badf2
10 1bb206dbdf18f75e4515aeef378ba50e555a9291 ima-ns sha256:795fb52db49b211450c7242dbcad00d782a7b8174f669c259f74a7ccabe03a90 /usr/bin/id e496e384-4133-4d57-b93a-1812b83badf2

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 include/linux/ima.h                       |  1 +
 security/integrity/ima/Kconfig            |  6 +++++-
 security/integrity/ima/ima_template.c     |  6 +++++-
 security/integrity/ima/ima_template_lib.c | 24 ++++++++++++++++++++++-
 security/integrity/ima/ima_template_lib.h |  4 ++++
 5 files changed, 38 insertions(+), 3 deletions(-)

Comments

Serge Hallyn Nov. 29, 2021, 2:52 a.m. UTC | #1
On Sat, Nov 27, 2021 at 04:45:48PM +0000, James Bottomley wrote:
> Use the user namespace as the basis for namespacing IMA.  The
> implementation is very simple: add a new template called 'ima-ns'
> which exports the uuid of the user namespace into the IMA log.  This
> can be used to uniquely separate every container in the IMA log.
> 
> Note that the admin of the user namespace still cannot read back the
> IMA log because the IMA securityfs entries are not yet namespace
> aware.  However, root in the init_user_ns can read the log and see the
> containers.
> 
> You can get the uuid of init_user_ns from the boot_aggregate entry
> which is always the first one recorded in the log.  Any execution with
> a different uuid is in a new IMA namespace.
> 
> A sample of the log showing entry into a container is:
> 
> 10 7766c926c9db8dd4c923f96be5635b04593029c1 ima-ns sha256:0000000000000000000000000000000000000000000000000000000000000000 boot_aggregate 6582e360-1354-42b9-a6ef-ee1993d982da
> [...]
> 10 e0355132472d4d0ae1cc044412b4033bd5e1a48a ima-ns sha256:353e4d6b807056757fb5df31bafe7df80605bec20b445d5e9afd949ca4147d49 /usr/bin/unshare 6582e360-1354-42b9-a6ef-ee1993d982da
> 10 f257f5a12fd6e28d32b367a2e453c3badd0e8774 ima-ns sha256:2a7c66fc7e19acc100ee2b777b71179043fade8b81968828522cf31e6a96eaa7 /usr/bin/bash e496e384-4133-4d57-b93a-1812b83badf2
> 10 1bb206dbdf18f75e4515aeef378ba50e555a9291 ima-ns sha256:795fb52db49b211450c7242dbcad00d782a7b8174f669c259f74a7ccabe03a90 /usr/bin/id e496e384-4133-4d57-b93a-1812b83badf2
> 
> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

Acked-by: Serge Hallyn <serge@hallyn.com>

> ---
>  include/linux/ima.h                       |  1 +
>  security/integrity/ima/Kconfig            |  6 +++++-
>  security/integrity/ima/ima_template.c     |  6 +++++-
>  security/integrity/ima/ima_template_lib.c | 24 ++++++++++++++++++++++-
>  security/integrity/ima/ima_template_lib.h |  4 ++++
>  5 files changed, 38 insertions(+), 3 deletions(-)
> 
> diff --git a/include/linux/ima.h b/include/linux/ima.h
> index b6ab66a546ae..09b14b73889e 100644
> --- a/include/linux/ima.h
> +++ b/include/linux/ima.h
> @@ -11,6 +11,7 @@
>  #include <linux/fs.h>
>  #include <linux/security.h>
>  #include <linux/kexec.h>
> +#include <linux/user_namespace.h>
>  #include <crypto/hash_info.h>
>  struct linux_binprm;
>  
> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index f3a9cc201c8c..4f0ce241b585 100644
> --- a/security/integrity/ima/Kconfig
> +++ b/security/integrity/ima/Kconfig
> @@ -69,7 +69,8 @@ choice
>  	  hash, defined as 20 bytes, and a null terminated pathname,
>  	  limited to 255 characters.  The 'ima-ng' measurement list
>  	  template permits both larger hash digests and longer
> -	  pathnames.
> +	  pathnames.  The 'ima-ns' adds the namespace uuid to the
> +	  'ima-ng' template.
>  
>  	config IMA_TEMPLATE
>  		bool "ima"
> @@ -77,6 +78,8 @@ choice
>  		bool "ima-ng (default)"
>  	config IMA_SIG_TEMPLATE
>  		bool "ima-sig"
> +	config IMA_NS_TEMPLATE
> +		bool "ima-ns"
>  endchoice
>  
>  config IMA_DEFAULT_TEMPLATE
> @@ -85,6 +88,7 @@ config IMA_DEFAULT_TEMPLATE
>  	default "ima" if IMA_TEMPLATE
>  	default "ima-ng" if IMA_NG_TEMPLATE
>  	default "ima-sig" if IMA_SIG_TEMPLATE
> +	default "ima-ns" if IMA_NS_TEMPLATE
>  
>  choice
>  	prompt "Default integrity hash algorithm"
> diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
> index 694560396be0..14e02eb3d0f3 100644
> --- a/security/integrity/ima/ima_template.c
> +++ b/security/integrity/ima/ima_template.c
> @@ -24,6 +24,7 @@ static struct ima_template_desc builtin_templates[] = {
>  	{.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"},
>  	{.name = "evm-sig",
>  	 .fmt = "d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode"},
> +	{.name = "ima-ns", .fmt = "d-ng|n-ng|ns"},
>  	{.name = "", .fmt = ""},	/* placeholder for a custom format */
>  };
>  
> @@ -64,6 +65,9 @@ static const struct ima_template_field supported_fields[] = {
>  	{.field_id = "xattrvalues",
>  	 .field_init = ima_eventinodexattrvalues_init,
>  	 .field_show = ima_show_template_sig},
> +	{.field_id = "ns",
> +	 .field_init = ima_ns_init,
> +	 .field_show = ima_show_template_uuid},
>  };
>  
>  /*
> @@ -72,7 +76,7 @@ static const struct ima_template_field supported_fields[] = {
>   * description as 'd-ng' and 'n-ng' respectively.
>   */
>  #define MAX_TEMPLATE_NAME_LEN \
> -	sizeof("d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode")
> +	sizeof("d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode|ns")
>  
>  static struct ima_template_desc *ima_template;
>  static struct ima_template_desc *ima_buf_template;
> diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
> index ca017cae73eb..ebd54c1b5206 100644
> --- a/security/integrity/ima/ima_template_lib.c
> +++ b/security/integrity/ima/ima_template_lib.c
> @@ -26,7 +26,8 @@ enum data_formats {
>  	DATA_FMT_DIGEST_WITH_ALGO,
>  	DATA_FMT_STRING,
>  	DATA_FMT_HEX,
> -	DATA_FMT_UINT
> +	DATA_FMT_UINT,
> +	DATA_FMT_UUID,
>  };
>  
>  static int ima_write_template_field_data(const void *data, const u32 datalen,
> @@ -120,6 +121,9 @@ static void ima_show_template_data_ascii(struct seq_file *m,
>  			break;
>  		}
>  		break;
> +	case DATA_FMT_UUID:
> +		seq_printf(m, "%pU", buf_ptr);
> +		break;
>  	default:
>  		break;
>  	}
> @@ -202,6 +206,12 @@ void ima_show_template_uint(struct seq_file *m, enum ima_show_type show,
>  	ima_show_template_field_data(m, show, DATA_FMT_UINT, field_data);
>  }
>  
> +void ima_show_template_uuid(struct seq_file *m, enum ima_show_type show,
> +			    struct ima_field_data *field_data)
> +{
> +	ima_show_template_field_data(m, show, DATA_FMT_UUID, field_data);
> +}
> +
>  /**
>   * ima_parse_buf() - Parses lengths and data from an input buffer
>   * @bufstartp:       Buffer start address.
> @@ -685,3 +695,15 @@ int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
>  {
>  	return ima_eventinodexattrs_init_common(event_data, field_data, 'v');
>  }
> +
> +/*
> + *  ima_ns_init - include the namespace UUID as part of the template
> + *  data
> + */
> +int ima_ns_init(struct ima_event_data *event_data,
> +		struct ima_field_data *field_data)
> +{
> +	return ima_write_template_field_data(&current_user_ns()->uuid,
> +					     UUID_SIZE, DATA_FMT_UUID,
> +					     field_data);
> +}
> diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
> index c71f1de95753..6ea2156271ae 100644
> --- a/security/integrity/ima/ima_template_lib.h
> +++ b/security/integrity/ima/ima_template_lib.h
> @@ -29,6 +29,8 @@ void ima_show_template_buf(struct seq_file *m, enum ima_show_type show,
>  			   struct ima_field_data *field_data);
>  void ima_show_template_uint(struct seq_file *m, enum ima_show_type show,
>  			    struct ima_field_data *field_data);
> +void ima_show_template_uuid(struct seq_file *m, enum ima_show_type show,
> +			    struct ima_field_data *field_data);
>  int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
>  		  int maxfields, struct ima_field_data *fields, int *curfields,
>  		  unsigned long *len_mask, int enforce_mask, char *bufname);
> @@ -62,4 +64,6 @@ int ima_eventinodexattrlengths_init(struct ima_event_data *event_data,
>  				    struct ima_field_data *field_data);
>  int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
>  				   struct ima_field_data *field_data);
> +int ima_ns_init(struct ima_event_data *event_data,
> +		struct ima_field_data *field_data);
>  #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
> -- 
> 2.33.0
diff mbox series

Patch

diff --git a/include/linux/ima.h b/include/linux/ima.h
index b6ab66a546ae..09b14b73889e 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -11,6 +11,7 @@ 
 #include <linux/fs.h>
 #include <linux/security.h>
 #include <linux/kexec.h>
+#include <linux/user_namespace.h>
 #include <crypto/hash_info.h>
 struct linux_binprm;
 
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index f3a9cc201c8c..4f0ce241b585 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -69,7 +69,8 @@  choice
 	  hash, defined as 20 bytes, and a null terminated pathname,
 	  limited to 255 characters.  The 'ima-ng' measurement list
 	  template permits both larger hash digests and longer
-	  pathnames.
+	  pathnames.  The 'ima-ns' adds the namespace uuid to the
+	  'ima-ng' template.
 
 	config IMA_TEMPLATE
 		bool "ima"
@@ -77,6 +78,8 @@  choice
 		bool "ima-ng (default)"
 	config IMA_SIG_TEMPLATE
 		bool "ima-sig"
+	config IMA_NS_TEMPLATE
+		bool "ima-ns"
 endchoice
 
 config IMA_DEFAULT_TEMPLATE
@@ -85,6 +88,7 @@  config IMA_DEFAULT_TEMPLATE
 	default "ima" if IMA_TEMPLATE
 	default "ima-ng" if IMA_NG_TEMPLATE
 	default "ima-sig" if IMA_SIG_TEMPLATE
+	default "ima-ns" if IMA_NS_TEMPLATE
 
 choice
 	prompt "Default integrity hash algorithm"
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index 694560396be0..14e02eb3d0f3 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -24,6 +24,7 @@  static struct ima_template_desc builtin_templates[] = {
 	{.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"},
 	{.name = "evm-sig",
 	 .fmt = "d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode"},
+	{.name = "ima-ns", .fmt = "d-ng|n-ng|ns"},
 	{.name = "", .fmt = ""},	/* placeholder for a custom format */
 };
 
@@ -64,6 +65,9 @@  static const struct ima_template_field supported_fields[] = {
 	{.field_id = "xattrvalues",
 	 .field_init = ima_eventinodexattrvalues_init,
 	 .field_show = ima_show_template_sig},
+	{.field_id = "ns",
+	 .field_init = ima_ns_init,
+	 .field_show = ima_show_template_uuid},
 };
 
 /*
@@ -72,7 +76,7 @@  static const struct ima_template_field supported_fields[] = {
  * description as 'd-ng' and 'n-ng' respectively.
  */
 #define MAX_TEMPLATE_NAME_LEN \
-	sizeof("d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode")
+	sizeof("d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode|ns")
 
 static struct ima_template_desc *ima_template;
 static struct ima_template_desc *ima_buf_template;
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index ca017cae73eb..ebd54c1b5206 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -26,7 +26,8 @@  enum data_formats {
 	DATA_FMT_DIGEST_WITH_ALGO,
 	DATA_FMT_STRING,
 	DATA_FMT_HEX,
-	DATA_FMT_UINT
+	DATA_FMT_UINT,
+	DATA_FMT_UUID,
 };
 
 static int ima_write_template_field_data(const void *data, const u32 datalen,
@@ -120,6 +121,9 @@  static void ima_show_template_data_ascii(struct seq_file *m,
 			break;
 		}
 		break;
+	case DATA_FMT_UUID:
+		seq_printf(m, "%pU", buf_ptr);
+		break;
 	default:
 		break;
 	}
@@ -202,6 +206,12 @@  void ima_show_template_uint(struct seq_file *m, enum ima_show_type show,
 	ima_show_template_field_data(m, show, DATA_FMT_UINT, field_data);
 }
 
+void ima_show_template_uuid(struct seq_file *m, enum ima_show_type show,
+			    struct ima_field_data *field_data)
+{
+	ima_show_template_field_data(m, show, DATA_FMT_UUID, field_data);
+}
+
 /**
  * ima_parse_buf() - Parses lengths and data from an input buffer
  * @bufstartp:       Buffer start address.
@@ -685,3 +695,15 @@  int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
 {
 	return ima_eventinodexattrs_init_common(event_data, field_data, 'v');
 }
+
+/*
+ *  ima_ns_init - include the namespace UUID as part of the template
+ *  data
+ */
+int ima_ns_init(struct ima_event_data *event_data,
+		struct ima_field_data *field_data)
+{
+	return ima_write_template_field_data(&current_user_ns()->uuid,
+					     UUID_SIZE, DATA_FMT_UUID,
+					     field_data);
+}
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
index c71f1de95753..6ea2156271ae 100644
--- a/security/integrity/ima/ima_template_lib.h
+++ b/security/integrity/ima/ima_template_lib.h
@@ -29,6 +29,8 @@  void ima_show_template_buf(struct seq_file *m, enum ima_show_type show,
 			   struct ima_field_data *field_data);
 void ima_show_template_uint(struct seq_file *m, enum ima_show_type show,
 			    struct ima_field_data *field_data);
+void ima_show_template_uuid(struct seq_file *m, enum ima_show_type show,
+			    struct ima_field_data *field_data);
 int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
 		  int maxfields, struct ima_field_data *fields, int *curfields,
 		  unsigned long *len_mask, int enforce_mask, char *bufname);
@@ -62,4 +64,6 @@  int ima_eventinodexattrlengths_init(struct ima_event_data *event_data,
 				    struct ima_field_data *field_data);
 int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
 				   struct ima_field_data *field_data);
+int ima_ns_init(struct ima_event_data *event_data,
+		struct ima_field_data *field_data);
 #endif /* __LINUX_IMA_TEMPLATE_LIB_H */