[v6,04/10] ima: maintain memory size needed for serializing the measurement list
diff mbox

Message ID 1477017898-10375-5-git-send-email-bauerman@linux.vnet.ibm.com
State New
Headers show

Commit Message

Thiago Jung Bauermann Oct. 21, 2016, 2:44 a.m. UTC
From: Mimi Zohar <zohar@linux.vnet.ibm.com>

In preparation for serializing the binary_runtime_measurements, this patch
maintains the amount of memory required.

Changelog v5:
- replace CONFIG_KEXEC_FILE with architecture CONFIG_HAVE_IMA_KEXEC (Thiago)

Changelog v3:
- include the ima_kexec_hdr size in the binary_runtime_measurement size.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
 security/integrity/ima/Kconfig     | 12 +++++++++
 security/integrity/ima/ima.h       |  1 +
 security/integrity/ima/ima_queue.c | 53 ++++++++++++++++++++++++++++++++++++--
 3 files changed, 64 insertions(+), 2 deletions(-)

Comments

Dmitry Kasatkin Nov. 8, 2016, 8:05 p.m. UTC | #1
On Fri, Oct 21, 2016 at 5:44 AM, Thiago Jung Bauermann
<bauerman@linux.vnet.ibm.com> wrote:
> From: Mimi Zohar <zohar@linux.vnet.ibm.com>
>
> In preparation for serializing the binary_runtime_measurements, this patch
> maintains the amount of memory required.
>
> Changelog v5:
> - replace CONFIG_KEXEC_FILE with architecture CONFIG_HAVE_IMA_KEXEC (Thiago)
>
> Changelog v3:
> - include the ima_kexec_hdr size in the binary_runtime_measurement size.
>
> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
> ---
>  security/integrity/ima/Kconfig     | 12 +++++++++
>  security/integrity/ima/ima.h       |  1 +
>  security/integrity/ima/ima_queue.c | 53 ++++++++++++++++++++++++++++++++++++--
>  3 files changed, 64 insertions(+), 2 deletions(-)
>
> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index 5487827fa86c..370eb2f4dd37 100644
> --- a/security/integrity/ima/Kconfig
> +++ b/security/integrity/ima/Kconfig
> @@ -27,6 +27,18 @@ config IMA
>           to learn more about IMA.
>           If unsure, say N.
>
> +config IMA_KEXEC
> +       bool "Enable carrying the IMA measurement list across a soft boot"
> +       depends on IMA && TCG_TPM && HAVE_IMA_KEXEC
> +       default n
> +       help
> +          TPM PCRs are only reset on a hard reboot.  In order to validate
> +          a TPM's quote after a soft boot, the IMA measurement list of the
> +          running kernel must be saved and restored on boot.
> +
> +          Depending on the IMA policy, the measurement list can grow to
> +          be very large.
> +
>  config IMA_MEASURE_PCR_IDX
>         int
>         depends on IMA
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 51dc8d57d64d..ea1dcc452911 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -143,6 +143,7 @@ void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
>  struct ima_template_desc *ima_template_desc_current(void);
>  int ima_restore_measurement_entry(struct ima_template_entry *entry);
>  int ima_restore_measurement_list(loff_t bufsize, void *buf);
> +unsigned long ima_get_binary_runtime_size(void);
>  int ima_init_template(void);
>
>  /*
> diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> index 12d1b040bca9..3a3cc2a45645 100644
> --- a/security/integrity/ima/ima_queue.c
> +++ b/security/integrity/ima/ima_queue.c
> @@ -29,6 +29,11 @@
>  #define AUDIT_CAUSE_LEN_MAX 32
>
>  LIST_HEAD(ima_measurements);   /* list of all measurements */
> +#ifdef CONFIG_IMA_KEXEC
> +static unsigned long binary_runtime_size;
> +#else
> +static unsigned long binary_runtime_size = ULONG_MAX;
> +#endif
>
>  /* key: inode (before secure-hashing a file) */
>  struct ima_h_table ima_htable = {
> @@ -64,6 +69,24 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
>         return ret;
>  }
>
> +/*
> + * Calculate the memory required for serializing a single
> + * binary_runtime_measurement list entry, which contains a
> + * couple of variable length fields (e.g template name and data).
> + */
> +static int get_binary_runtime_size(struct ima_template_entry *entry)
> +{
> +       int size = 0;
> +
> +       size += sizeof(u32);    /* pcr */
> +       size += sizeof(entry->digest);
> +       size += sizeof(int);    /* template name size field */
> +       size += strlen(entry->template_desc->name);
> +       size += sizeof(entry->template_data_len);
> +       size += entry->template_data_len;
> +       return size;
> +}
> +

strlen returns len without '\0'. I cannot see how you would know how
to read it back?


>  /* ima_add_template_entry helper function:
>   * - Add template entry to the measurement list and hash table, for
>   *   all entries except those carried across kexec.
> @@ -90,9 +113,30 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
>                 key = ima_hash_key(entry->digest);
>                 hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
>         }
> +
> +       if (binary_runtime_size != ULONG_MAX) {
> +               int size;
> +
> +               size = get_binary_runtime_size(entry);
> +               binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
> +                    binary_runtime_size + size : ULONG_MAX;
> +       }
>         return 0;
>  }
>
> +/*
> + * Return the amount of memory required for serializing the
> + * entire binary_runtime_measurement list, including the ima_kexec_hdr
> + * structure.
> + */
> +unsigned long ima_get_binary_runtime_size(void)
> +{
> +       if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
> +               return ULONG_MAX;
> +       else
> +               return binary_runtime_size + sizeof(struct ima_kexec_hdr);
> +};
> +
>  static int ima_pcr_extend(const u8 *hash, int pcr)
>  {
>         int result = 0;
> @@ -106,8 +150,13 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
>         return result;
>  }
>
> -/* Add template entry to the measurement list and hash table,
> - * and extend the pcr.
> +/*
> + * Add template entry to the measurement list and hash table, and
> + * extend the pcr.
> + *
> + * On systems which support carrying the IMA measurement list across
> + * kexec, maintain the total memory size required for serializing the
> + * binary_runtime_measurements.
>   */
>  int ima_add_template_entry(struct ima_template_entry *entry, int violation,
>                            const char *op, struct inode *inode,
> --
> 2.7.4
>
>
> ------------------------------------------------------------------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, SlashDot.org! http://sdm.link/slashdot
> _______________________________________________
> Linux-ima-devel mailing list
> Linux-ima-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-ima-devel
Mimi Zohar Nov. 8, 2016, 9:03 p.m. UTC | #2
On Tue, 2016-11-08 at 22:05 +0200, Dmitry Kasatkin wrote:
> On Fri, Oct 21, 2016 at 5:44 AM, Thiago Jung Bauermann
> <bauerman@linux.vnet.ibm.com> wrote:
> > From: Mimi Zohar <zohar@linux.vnet.ibm.com>
> >
> > In preparation for serializing the binary_runtime_measurements, this patch
> > maintains the amount of memory required.
> >
> > Changelog v5:
> > - replace CONFIG_KEXEC_FILE with architecture CONFIG_HAVE_IMA_KEXEC (Thiago)
> >
> > Changelog v3:
> > - include the ima_kexec_hdr size in the binary_runtime_measurement size.
> >
> > Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
> > ---
> >  security/integrity/ima/Kconfig     | 12 +++++++++
> >  security/integrity/ima/ima.h       |  1 +
> >  security/integrity/ima/ima_queue.c | 53 ++++++++++++++++++++++++++++++++++++--
> >  3 files changed, 64 insertions(+), 2 deletions(-)
> >
> > diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> > index 5487827fa86c..370eb2f4dd37 100644
> > --- a/security/integrity/ima/Kconfig
> > +++ b/security/integrity/ima/Kconfig
> > @@ -27,6 +27,18 @@ config IMA
> >           to learn more about IMA.
> >           If unsure, say N.
> >
> > +config IMA_KEXEC
> > +       bool "Enable carrying the IMA measurement list across a soft boot"
> > +       depends on IMA && TCG_TPM && HAVE_IMA_KEXEC
> > +       default n
> > +       help
> > +          TPM PCRs are only reset on a hard reboot.  In order to validate
> > +          a TPM's quote after a soft boot, the IMA measurement list of the
> > +          running kernel must be saved and restored on boot.
> > +
> > +          Depending on the IMA policy, the measurement list can grow to
> > +          be very large.
> > +
> >  config IMA_MEASURE_PCR_IDX
> >         int
> >         depends on IMA
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index 51dc8d57d64d..ea1dcc452911 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -143,6 +143,7 @@ void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
> >  struct ima_template_desc *ima_template_desc_current(void);
> >  int ima_restore_measurement_entry(struct ima_template_entry *entry);
> >  int ima_restore_measurement_list(loff_t bufsize, void *buf);
> > +unsigned long ima_get_binary_runtime_size(void);
> >  int ima_init_template(void);
> >
> >  /*
> > diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
> > index 12d1b040bca9..3a3cc2a45645 100644
> > --- a/security/integrity/ima/ima_queue.c
> > +++ b/security/integrity/ima/ima_queue.c
> > @@ -29,6 +29,11 @@
> >  #define AUDIT_CAUSE_LEN_MAX 32
> >
> >  LIST_HEAD(ima_measurements);   /* list of all measurements */
> > +#ifdef CONFIG_IMA_KEXEC
> > +static unsigned long binary_runtime_size;
> > +#else
> > +static unsigned long binary_runtime_size = ULONG_MAX;
> > +#endif
> >
> >  /* key: inode (before secure-hashing a file) */
> >  struct ima_h_table ima_htable = {
> > @@ -64,6 +69,24 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
> >         return ret;
> >  }
> >
> > +/*
> > + * Calculate the memory required for serializing a single
> > + * binary_runtime_measurement list entry, which contains a
> > + * couple of variable length fields (e.g template name and data).
> > + */
> > +static int get_binary_runtime_size(struct ima_template_entry *entry)
> > +{
> > +       int size = 0;
> > +
> > +       size += sizeof(u32);    /* pcr */
> > +       size += sizeof(entry->digest);
> > +       size += sizeof(int);    /* template name size field */
> > +       size += strlen(entry->template_desc->name);
> > +       size += sizeof(entry->template_data_len);
> > +       size += entry->template_data_len;
> > +       return size;
> > +}
> > +
> 
> strlen returns len without '\0'. I cannot see how you would know how
> to read it back?

This function is used to keep a running memory size needed for
allocating the buffer to carry the measurement list across kexec.

Right, the memory need for the template name is +1.

Mimi

> 
> >  /* ima_add_template_entry helper function:
> >   * - Add template entry to the measurement list and hash table, for
> >   *   all entries except those carried across kexec.
> > @@ -90,9 +113,30 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
> >                 key = ima_hash_key(entry->digest);
> >                 hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
> >         }
> > +
> > +       if (binary_runtime_size != ULONG_MAX) {
> > +               int size;
> > +
> > +               size = get_binary_runtime_size(entry);
> > +               binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
> > +                    binary_runtime_size + size : ULONG_MAX;
> > +       }
> >         return 0;
> >  }
> >
> > +/*
> > + * Return the amount of memory required for serializing the
> > + * entire binary_runtime_measurement list, including the ima_kexec_hdr
> > + * structure.
> > + */
> > +unsigned long ima_get_binary_runtime_size(void)
> > +{
> > +       if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
> > +               return ULONG_MAX;
> > +       else
> > +               return binary_runtime_size + sizeof(struct ima_kexec_hdr);
> > +};
> > +
> >  static int ima_pcr_extend(const u8 *hash, int pcr)
> >  {
> >         int result = 0;
> > @@ -106,8 +150,13 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
> >         return result;
> >  }
> >
> > -/* Add template entry to the measurement list and hash table,
> > - * and extend the pcr.
> > +/*
> > + * Add template entry to the measurement list and hash table, and
> > + * extend the pcr.
> > + *
> > + * On systems which support carrying the IMA measurement list across
> > + * kexec, maintain the total memory size required for serializing the
> > + * binary_runtime_measurements.
> >   */
> >  int ima_add_template_entry(struct ima_template_entry *entry, int violation,
> >                            const char *op, struct inode *inode,
> > --
> > 2.7.4


--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 5487827fa86c..370eb2f4dd37 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -27,6 +27,18 @@  config IMA
 	  to learn more about IMA.
 	  If unsure, say N.
 
+config IMA_KEXEC
+	bool "Enable carrying the IMA measurement list across a soft boot"
+	depends on IMA && TCG_TPM && HAVE_IMA_KEXEC
+	default n
+	help
+	   TPM PCRs are only reset on a hard reboot.  In order to validate
+	   a TPM's quote after a soft boot, the IMA measurement list of the
+	   running kernel must be saved and restored on boot.
+
+	   Depending on the IMA policy, the measurement list can grow to
+	   be very large.
+
 config IMA_MEASURE_PCR_IDX
 	int
 	depends on IMA
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 51dc8d57d64d..ea1dcc452911 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -143,6 +143,7 @@  void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
 struct ima_template_desc *ima_template_desc_current(void);
 int ima_restore_measurement_entry(struct ima_template_entry *entry);
 int ima_restore_measurement_list(loff_t bufsize, void *buf);
+unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
 
 /*
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 12d1b040bca9..3a3cc2a45645 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -29,6 +29,11 @@ 
 #define AUDIT_CAUSE_LEN_MAX 32
 
 LIST_HEAD(ima_measurements);	/* list of all measurements */
+#ifdef CONFIG_IMA_KEXEC
+static unsigned long binary_runtime_size;
+#else
+static unsigned long binary_runtime_size = ULONG_MAX;
+#endif
 
 /* key: inode (before secure-hashing a file) */
 struct ima_h_table ima_htable = {
@@ -64,6 +69,24 @@  static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
 	return ret;
 }
 
+/*
+ * Calculate the memory required for serializing a single
+ * binary_runtime_measurement list entry, which contains a
+ * couple of variable length fields (e.g template name and data).
+ */
+static int get_binary_runtime_size(struct ima_template_entry *entry)
+{
+	int size = 0;
+
+	size += sizeof(u32);	/* pcr */
+	size += sizeof(entry->digest);
+	size += sizeof(int);	/* template name size field */
+	size += strlen(entry->template_desc->name);
+	size += sizeof(entry->template_data_len);
+	size += entry->template_data_len;
+	return size;
+}
+
 /* ima_add_template_entry helper function:
  * - Add template entry to the measurement list and hash table, for
  *   all entries except those carried across kexec.
@@ -90,9 +113,30 @@  static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
 		key = ima_hash_key(entry->digest);
 		hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
 	}
+
+	if (binary_runtime_size != ULONG_MAX) {
+		int size;
+
+		size = get_binary_runtime_size(entry);
+		binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
+		     binary_runtime_size + size : ULONG_MAX;
+	}
 	return 0;
 }
 
+/*
+ * Return the amount of memory required for serializing the
+ * entire binary_runtime_measurement list, including the ima_kexec_hdr
+ * structure.
+ */
+unsigned long ima_get_binary_runtime_size(void)
+{
+	if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
+		return ULONG_MAX;
+	else
+		return binary_runtime_size + sizeof(struct ima_kexec_hdr);
+};
+
 static int ima_pcr_extend(const u8 *hash, int pcr)
 {
 	int result = 0;
@@ -106,8 +150,13 @@  static int ima_pcr_extend(const u8 *hash, int pcr)
 	return result;
 }
 
-/* Add template entry to the measurement list and hash table,
- * and extend the pcr.
+/*
+ * Add template entry to the measurement list and hash table, and
+ * extend the pcr.
+ *
+ * On systems which support carrying the IMA measurement list across
+ * kexec, maintain the total memory size required for serializing the
+ * binary_runtime_measurements.
  */
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 			   const char *op, struct inode *inode,