[PATCH v3 9/9] ima: platform-independent hash value

2016-09-06 Thread Mimi Zohar
From: Andreas Steffen <andreas.stef...@strongswan.org>

For remote attestion it is important for the ima measurement values
to be platform-independent. Therefore integer fields to be hashed
must be converted to canonical format.

Changelog:
- Define canonical format as little endian (Mimi)

Signed-off-by: Andreas Steffen <andreas.stef...@strongswan.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_crypto.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index 38f2ed8..802d5d2 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -477,11 +477,13 @@ static int ima_calc_field_array_hash_tfm(struct 
ima_field_data *field_data,
u8 buffer[IMA_EVENT_NAME_LEN_MAX + 1] = { 0 };
u8 *data_to_hash = field_data[i].data;
u32 datalen = field_data[i].len;
+   u32 datalen_to_hash =
+   !ima_canonical_fmt ? datalen : cpu_to_le32(datalen);
 
if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
rc = crypto_shash_update(shash,
-   (const u8 *) _data[i].len,
-   sizeof(field_data[i].len));
+   (const u8 *) _to_hash,
+   sizeof(datalen_to_hash));
if (rc)
break;
} else if (strcmp(td->fields[i]->field_id, "n") == 0) {
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 2/9] ima: permit duplicate measurement list entries

2016-09-06 Thread Mimi Zohar
Measurements carried across kexec need to be added to the IMA
measurement list, but should not prevent measurements of the newly
booted kernel from being added to the measurement list. This patch
adds support for allowing duplicate measurements.

The "boot_aggregate" measurement entry is the delimiter between soft
boots.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_queue.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_queue.c 
b/security/integrity/ima/ima_queue.c
index 4b1bb77..12d1b04 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -65,11 +65,12 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 
*digest_value,
 }
 
 /* ima_add_template_entry helper function:
- * - Add template entry to measurement list and hash table.
+ * - Add template entry to the measurement list and hash table, for
+ *   all entries except those carried across kexec.
  *
  * (Called with ima_extend_list_mutex held.)
  */
-static int ima_add_digest_entry(struct ima_template_entry *entry)
+static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
 {
struct ima_queue_entry *qe;
unsigned int key;
@@ -85,8 +86,10 @@ static int ima_add_digest_entry(struct ima_template_entry 
*entry)
list_add_tail_rcu(>later, _measurements);
 
atomic_long_inc(_htable.len);
-   key = ima_hash_key(entry->digest);
-   hlist_add_head_rcu(>hnext, _htable.queue[key]);
+   if (flags) {
+   key = ima_hash_key(entry->digest);
+   hlist_add_head_rcu(>hnext, _htable.queue[key]);
+   }
return 0;
 }
 
@@ -126,7 +129,7 @@ int ima_add_template_entry(struct ima_template_entry 
*entry, int violation,
}
}
 
-   result = ima_add_digest_entry(entry);
+   result = ima_add_digest_entry(entry, 1);
if (result < 0) {
audit_cause = "ENOMEM";
audit_info = 0;
@@ -155,7 +158,7 @@ int ima_restore_measurement_entry(struct ima_template_entry 
*entry)
int result = 0;
 
mutex_lock(_extend_list_mutex);
-   result = ima_add_digest_entry(entry);
+   result = ima_add_digest_entry(entry, 0);
mutex_unlock(_extend_list_mutex);
return result;
 }
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 3/9] ima: maintain memory size needed for serializing the measurement list

2016-09-06 Thread Mimi Zohar
In preparation for serializing the binary_runtime_measurements, this patch
maintains the amount of memory required.

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

Signed-off-by: Mimi Zohar <zo...@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 5487827..1c5a1c2 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 && KEXEC_FILE
+   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 e7b3755..f9cd08e 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -133,6 +133,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);
 
 #ifdef CONFIG_KEXEC_FILE
diff --git a/security/integrity/ima/ima_queue.c 
b/security/integrity/ima/ima_queue.c
index 12d1b04..3a3cc2a 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(>hnext, _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.

[PATCH v3 0/9] ima: carry the measurement list across kexec

2016-09-06 Thread Mimi Zohar
The TPM PCRs are only reset on a hard reboot.  In order to validate a
TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
of the running kernel must be saved and then restored on the subsequent
boot, possibly of a different architecture.

The existing securityfs binary_runtime_measurements file conveniently
provides a serialized format of the IMA measurement list. This patch
set serializes the measurement list in this format and restores it.

Up to now, the binary_runtime_measurements was defined as architecture
native format.  The assumption being that userspace could and would
handle any architecture conversions.  With the ability of carrying the
measurement list across kexec, possibly from one architecture to a
different one, the per boot architecture information is lost and with it
the ability of recalculating the template digest hash.  To resolve this
problem, without breaking the existing ABI, this patch set introduces
the boot command line option "ima_canonical_fmt", which is arbitrarily
defined as little endian.

The need for this boot command line option will be limited to the
existing version 1 format of the binary_runtime_measurements.
Subsequent formats will be defined as canonical format (eg. TPM 2.0
support for larger digests).

This patch set pre-req's Thiago Bauermann's "kexec_file: Add buffer
hand-over for the next kernel" patch set. 

These patches can also be found in the next-kexec-restore branch of:
git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git

Changelog v3:
- Cleaned up the code for calculating the requested kexec segment size
needed for the IMA measurement list, limiting the segment size to half
of the totalram_pages.
- Fixed kernel test robot reports as enumerated in the respective
patch changelog.

Changelog v2:
- Canonical measurement list support added
- Redefined the ima_kexec_hdr struct to use well defined sizes

Mimi

Andreas Steffen (1):
  ima: platform-independent hash value

Mimi Zohar (7):
  ima: on soft reboot, restore the measurement list
  ima: permit duplicate measurement list entries
  ima: maintain memory size needed for serializing the measurement list
  ima: serialize the binary_runtime_measurements
  ima: store the builtin/custom template definitions in a list
  ima: support restoring multiple template formats
  ima: define a canonical binary_runtime_measurements list format

Thiago Jung Bauermann (1):
  ima: on soft reboot, save the measurement list

 Documentation/kernel-parameters.txt   |   4 +
 include/linux/ima.h   |  12 ++
 kernel/kexec_file.c   |   4 +
 security/integrity/ima/Kconfig|  12 ++
 security/integrity/ima/Makefile   |   1 +
 security/integrity/ima/ima.h  |  28 +++
 security/integrity/ima/ima_crypto.c   |   6 +-
 security/integrity/ima/ima_fs.c   |  30 ++-
 security/integrity/ima/ima_init.c |   2 +
 security/integrity/ima/ima_kexec.c| 209 +
 security/integrity/ima/ima_main.c |   1 +
 security/integrity/ima/ima_queue.c|  76 +++-
 security/integrity/ima/ima_template.c | 293 --
 security/integrity/ima/ima_template_lib.c |   7 +-
 14 files changed, 653 insertions(+), 32 deletions(-)
 create mode 100644 security/integrity/ima/ima_kexec.c

-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATHC v2 5/9] ima: on soft reboot, save the measurement list

2016-09-02 Thread Mimi Zohar
Hi Dave,

On Thu, 2016-09-01 at 09:57 +0800, Dave Young wrote:
> On 08/30/16 at 06:40pm, Mimi Zohar wrote:

> > + * Called during kexec_file_load so that IMA can add a segment to the kexec
> > + * image for the measurement list for the next kernel.
> > + */
> > +void ima_add_kexec_buffer(struct kimage *image)
> > +{
> > +   static int registered = 0;
> > +   struct kexec_buf kbuf = { .image = image, .buf_align = PAGE_SIZE,
> > + .buf_min = 0, .buf_max = ULONG_MAX,
> > + .top_down = true, .skip_checksum = true };
> > +   int ret;
> > +
> > +   if (!kexec_can_hand_over_buffer())
> > +   return;
> > +
> > +   kexec_segment_size = ALIGN(ima_get_binary_runtime_size() + PAGE_SIZE,
> > +  PAGE_SIZE);
> > +
> > +   if (kexec_segment_size >= (ULONG_MAX - sizeof(long))) {
> > +   pr_err("Binary measurement list too large.\n");
> > +   return;
> > +   }
> 
> Now we added a limitation that total segment size can not be larger than
> half of totalram. see kernel/kexec_core.c sanity_check_segment_list()
> 
> So can it fail early here if kexec_segment_size is over half of total
> ram?

Sure, I'll include this change in the next post.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATHC v2 0/9] ima: carry the measurement list across kexec

2016-08-31 Thread Mimi Zohar
On Wed, 2016-08-31 at 13:50 -0700, Andrew Morton wrote:
> On Tue, 30 Aug 2016 18:40:02 -0400 Mimi Zohar <zo...@linux.vnet.ibm.com> 
> wrote:
> 
> > The TPM PCRs are only reset on a hard reboot.  In order to validate a
> > TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
> > of the running kernel must be saved and then restored on the subsequent
> > boot, possibly of a different architecture.
> > 
> > The existing securityfs binary_runtime_measurements file conveniently
> > provides a serialized format of the IMA measurement list. This patch
> > set serializes the measurement list in this format and restores it.
> > 
> > Up to now, the binary_runtime_measurements was defined as architecture
> > native format.  The assumption being that userspace could and would
> > handle any architecture conversions.  With the ability of carrying the
> > measurement list across kexec, possibly from one architecture to a
> > different one, the per boot architecture information is lost and with it
> > the ability of recalculating the template digest hash.  To resolve this
> > problem, without breaking the existing ABI, this patch set introduces
> > the boot command line option "ima_canonical_fmt", which is arbitrarily
> > defined as little endian.
> > 
> > The need for this boot command line option will be limited to the
> > existing version 1 format of the binary_runtime_measurements.
> > Subsequent formats will be defined as canonical format (eg. TPM 2.0
> > support for larger digests).
> > 
> > This patch set pre-req's Thiago Bauermann's "kexec_file: Add buffer
> > hand-over for the next kernel" patch set. 
> > 
> > These patches can also be found in the next-kexec-restore branch of:
> > git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
> 
> I'll merge these into -mm to get some linux-next exposure.  I don't
> know what your upstream merge plans will be?

Sounds good.  I'm hoping to get some review/comments on this patch set
as well.  At the moment, I'm chasing down a kernel test robot report
from this afternoon.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATHC v2 9/9] ima: platform-independent hash value

2016-08-30 Thread Mimi Zohar
From: Andreas Steffen <andreas.stef...@strongswan.org>

For remote attestion it is important for the ima measurement values
to be platform-independent. Therefore integer fields to be hashed
must be converted to canonical format.

Changelog:
- Define canonical format as little endian (Mimi)

Signed-off-by: Andreas Steffen <andreas.stef...@strongswan.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_crypto.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index 38f2ed8..38d6f5d 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -477,11 +477,13 @@ static int ima_calc_field_array_hash_tfm(struct 
ima_field_data *field_data,
u8 buffer[IMA_EVENT_NAME_LEN_MAX + 1] = { 0 };
u8 *data_to_hash = field_data[i].data;
u32 datalen = field_data[i].len;
+   u32 datalen_to_hash = !ima_canonical_fmt ? datalen :
+   cpu_to_le32(datalen);
 
if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
rc = crypto_shash_update(shash,
-   (const u8 *) _data[i].len,
-   sizeof(field_data[i].len));
+   (const u8 *) _to_hash,
+   sizeof(datalen_to_hash));
if (rc)
break;
} else if (strcmp(td->fields[i]->field_id, "n") == 0) {
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATHC v2 3/9] ima: maintain memory size needed for serializing the measurement list

2016-08-30 Thread Mimi Zohar
In preparation for serializing the binary_runtime_measurements, this patch
maintains the amount of memory required.

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

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 5487827..1c5a1c2 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 && KEXEC_FILE
+   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 e7b3755..f9cd08e 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -133,6 +133,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);
 
 #ifdef CONFIG_KEXEC_FILE
diff --git a/security/integrity/ima/ima_queue.c 
b/security/integrity/ima/ima_queue.c
index 12d1b04..8f0661b 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,26 @@ static int ima_add_digest_entry(struct ima_template_entry 
*entry, int flags)
key = ima_hash_key(entry->digest);
hlist_add_head_rcu(>hnext, _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.
+ */
+unsigned long ima_get_binary_runtime_size(void)
+{
+   return binary_runtime_size;
+};
+
 static int ima_pcr_extend(const u8 *hash, int pcr)
 {
int result = 0;
@@ -106,8 +146,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.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATHC v2 6/9] ima: store the builtin/custom template definitions in a list

2016-08-30 Thread Mimi Zohar
The builtin and single custom templates are currently stored in an
array.  In preparation for being able to restore a measurement list
containing multiple builtin/custom templates, this patch stores the
builtin and custom templates as a linked list.  This will permit
defining more than one custom template per boot.

Changelog v2:
- fix lookup_template_desc() preemption imbalance (kernel test robot)

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h  |  2 ++
 security/integrity/ima/ima_main.c |  1 +
 security/integrity/ima/ima_template.c | 43 +++
 3 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 634d140..e8303c9 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -81,6 +81,7 @@ struct ima_template_field {
 
 /* IMA template descriptor definition */
 struct ima_template_desc {
+   struct list_head list;
char *name;
char *fmt;
int num_fields;
@@ -136,6 +137,7 @@ int ima_restore_measurement_list(loff_t bufsize, void *buf);
 int ima_measurements_show(struct seq_file *m, void *v);
 unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
+void ima_init_template_list(void);
 
 #ifdef CONFIG_KEXEC_FILE
 void ima_load_kexec_buffer(void);
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index 596ef61..592f318 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -418,6 +418,7 @@ static int __init init_ima(void)
 {
int error;
 
+   ima_init_template_list();
hash_setup(CONFIG_IMA_DEFAULT_HASH);
error = ima_init();
if (!error) {
diff --git a/security/integrity/ima/ima_template.c 
b/security/integrity/ima/ima_template.c
index 7c90075..92df055 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -15,16 +15,20 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include "ima.h"
 #include "ima_template_lib.h"
 
-static struct ima_template_desc defined_templates[] = {
+static struct ima_template_desc builtin_templates[] = {
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
{.name = "ima-ng", .fmt = "d-ng|n-ng"},
{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
{.name = "", .fmt = ""},/* placeholder for a custom format */
 };
 
+static LIST_HEAD(defined_templates);
+spinlock_t template_list;
+
 static struct ima_template_field supported_fields[] = {
{.field_id = "d", .field_init = ima_eventdigest_init,
 .field_show = ima_show_template_digest},
@@ -81,7 +85,7 @@ __setup("ima_template=", ima_template_setup);
 
 static int __init ima_template_fmt_setup(char *str)
 {
-   int num_templates = ARRAY_SIZE(defined_templates);
+   int num_templates = ARRAY_SIZE(builtin_templates);
 
if (ima_template)
return 1;
@@ -92,22 +96,28 @@ static int __init ima_template_fmt_setup(char *str)
return 1;
}
 
-   defined_templates[num_templates - 1].fmt = str;
-   ima_template = defined_templates + num_templates - 1;
+   builtin_templates[num_templates - 1].fmt = str;
+   ima_template = builtin_templates + num_templates - 1;
+
return 1;
 }
 __setup("ima_template_fmt=", ima_template_fmt_setup);
 
 static struct ima_template_desc *lookup_template_desc(const char *name)
 {
-   int i;
+   struct ima_template_desc *template_desc;
+   int found = 0;
 
-   for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
-   if (strcmp(defined_templates[i].name, name) == 0)
-   return defined_templates + i;
+   rcu_read_lock();
+   list_for_each_entry_rcu(template_desc, _templates, list) {
+   if ((strcmp(template_desc->name, name) == 0) ||
+   (strcmp(template_desc->fmt, name) == 0)) {
+   found = 1;
+   break;
+   }
}
-
-   return NULL;
+   rcu_read_unlock();
+   return found ? template_desc : NULL;
 }
 
 static struct ima_template_field *lookup_template_field(const char *field_id)
@@ -191,6 +201,19 @@ struct ima_template_desc *ima_template_desc_current(void)
return ima_template;
 }
 
+void __init ima_init_template_list(void)
+{
+   int i;
+
+   spin_lock(_list);
+   for (i = 0; i < ARRAY_SIZE(builtin_templates); i++) {
+   list_add_tail_rcu(_templates[i].list,
+ _templates);
+   }
+   spin_unlock(_list);
+   synchronize_rcu();
+}
+
 int __init ima_init_template(void)
 {
struct ima_template_desc *template = ima_template_desc_current();
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATHC v2 8/9] ima: define a canonical binary_runtime_measurements list format

2016-08-30 Thread Mimi Zohar
The IMA binary_runtime_measurements list is currently in platform native
format.

To allow restoring a measurement list carried across kexec with a
different endianness than the targeted kernel, this patch defines
little-endian as the canonical format.  For big endian systems wanting
to save/restore the measurement list from a system with a different
endianness, a new boot command line parameter named "ima_canonical_fmt"
is defined.

Considerations: use of the "ima_canonical_fmt" boot command line
option will break existing userspace applications on big endian systems
expecting the binary_runtime_measurements list to be in platform native
format.

Signed-off-by: Mimi Zohar <zo...@us.ibm.com>
---
 Documentation/kernel-parameters.txt   |  4 
 security/integrity/ima/ima.h  |  6 ++
 security/integrity/ima/ima_fs.c   | 28 +---
 security/integrity/ima/ima_kexec.c| 11 +--
 security/integrity/ima/ima_template.c | 24 ++--
 security/integrity/ima/ima_template_lib.c |  6 --
 6 files changed, 66 insertions(+), 13 deletions(-)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index 46c030a..5e8037fc 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1580,6 +1580,10 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
The builtin appraise policy appraises all files
owned by uid=0.
 
+   ima_canonical_fmt [IMA]
+   Use the canonical format for the binary runtime
+   measurements, instead of host native format.
+
ima_hash=   [IMA]
Format: { md5 | sha1 | rmd160 | sha256 | sha384
   | sha512 | ... }
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index e8303c9..eb0f4dd 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -112,6 +112,12 @@ struct ima_kexec_hdr {
u64 count;
 };
 
+/*
+ * The default binary_runtime_measurements list format is defined as the
+ * platform native format.  The canonical format is defined as little-endian.
+ */
+extern bool ima_canonical_fmt;
+
 /* Internal IMA function definitions */
 int ima_init(void);
 int ima_fs_init(void);
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 66e5dd5..2bcad99 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -28,6 +28,16 @@
 
 static DEFINE_MUTEX(ima_write_mutex);
 
+bool ima_canonical_fmt;
+static int __init default_canonical_fmt_setup(char *str)
+{
+#ifdef __BIG_ENDIAN
+   ima_canonical_fmt = 1;
+#endif
+   return 1;
+}
+__setup("ima_canonical_fmt", default_canonical_fmt_setup);
+
 static int valid_policy = 1;
 #define TMPBUFLEN 12
 static ssize_t ima_show_htable_value(char __user *buf, size_t count,
@@ -122,7 +132,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
struct ima_queue_entry *qe = v;
struct ima_template_entry *e;
char *template_name;
-   int namelen;
+   u32 pcr, namelen, template_data_len; /* temporary fields */
bool is_ima_template = false;
int i;
 
@@ -139,25 +149,29 @@ int ima_measurements_show(struct seq_file *m, void *v)
 * PCR used defaults to the same (config option) in
 * little-endian format, unless set in policy
 */
-   ima_putc(m, >pcr, sizeof(e->pcr));
+   pcr = !ima_canonical_fmt ? e->pcr : cpu_to_le32(e->pcr);
+   ima_putc(m, , sizeof(e->pcr));
 
/* 2nd: template digest */
ima_putc(m, e->digest, TPM_DIGEST_SIZE);
 
/* 3rd: template name size */
-   namelen = strlen(template_name);
+   namelen = !ima_canonical_fmt ? strlen(template_name) :
+   cpu_to_le32(strlen(template_name));
ima_putc(m, , sizeof(namelen));
 
/* 4th:  template name */
-   ima_putc(m, template_name, namelen);
+   ima_putc(m, template_name, strlen(template_name));
 
/* 5th:  template length (except for 'ima' template) */
if (strcmp(template_name, IMA_TEMPLATE_IMA_NAME) == 0)
is_ima_template = true;
 
-   if (!is_ima_template)
-   ima_putc(m, >template_data_len,
-sizeof(e->template_data_len));
+   if (!is_ima_template) {
+   template_data_len = !ima_canonical_fmt ? e->template_data_len :
+   cpu_to_le32(e->template_data_len);
+   ima_putc(m, _data_len, sizeof(e->template_data_len));
+   }
 
/* 6th:  template specific data */
for (i = 0; i < e->template_desc->num_fields; i++) {
diff --git a/security/integrity/ima/ima_kexec.c 
b/security/integrity/ima/ima_kexec.c
index 0e4d0db..cf38ccc 100644
---

[PATHC v2 0/9] ima: carry the measurement list across kexec

2016-08-30 Thread Mimi Zohar
The TPM PCRs are only reset on a hard reboot.  In order to validate a
TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
of the running kernel must be saved and then restored on the subsequent
boot, possibly of a different architecture.

The existing securityfs binary_runtime_measurements file conveniently
provides a serialized format of the IMA measurement list. This patch
set serializes the measurement list in this format and restores it.

Up to now, the binary_runtime_measurements was defined as architecture
native format.  The assumption being that userspace could and would
handle any architecture conversions.  With the ability of carrying the
measurement list across kexec, possibly from one architecture to a
different one, the per boot architecture information is lost and with it
the ability of recalculating the template digest hash.  To resolve this
problem, without breaking the existing ABI, this patch set introduces
the boot command line option "ima_canonical_fmt", which is arbitrarily
defined as little endian.

The need for this boot command line option will be limited to the
existing version 1 format of the binary_runtime_measurements.
Subsequent formats will be defined as canonical format (eg. TPM 2.0
support for larger digests).

This patch set pre-req's Thiago Bauermann's "kexec_file: Add buffer
hand-over for the next kernel" patch set. 

These patches can also be found in the next-kexec-restore branch of:
git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git

Mimi

Andreas Steffen (1):
  ima: platform-independent hash value

Mimi Zohar (7):
  ima: on soft reboot, restore the measurement list
  ima: permit duplicate measurement list entries
  ima: maintain memory size needed for serializing the measurement list
  ima: serialize the binary_runtime_measurements
  ima: store the builtin/custom template definitions in a list
  ima: support restoring multiple template formats
  ima: define a canonical binary_runtime_measurements list format

Thiago Jung Bauermann (1):
  ima: on soft reboot, save the measurement list

 Documentation/kernel-parameters.txt   |   4 +
 include/linux/ima.h   |  12 ++
 kernel/kexec_file.c   |   4 +
 security/integrity/ima/Kconfig|  12 ++
 security/integrity/ima/Makefile   |   1 +
 security/integrity/ima/ima.h  |  28 +++
 security/integrity/ima/ima_crypto.c   |   6 +-
 security/integrity/ima/ima_fs.c   |  30 +++-
 security/integrity/ima/ima_init.c |   2 +
 security/integrity/ima/ima_kexec.c| 201 +
 security/integrity/ima/ima_main.c |   1 +
 security/integrity/ima/ima_queue.c|  72 +++-
 security/integrity/ima/ima_template.c | 289 --
 security/integrity/ima/ima_template_lib.c |   6 +-
 14 files changed, 637 insertions(+), 31 deletions(-)
 create mode 100644 security/integrity/ima/ima_kexec.c

-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATHC v2 5/9] ima: on soft reboot, save the measurement list

2016-08-30 Thread Mimi Zohar
From: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

This patch uses the kexec buffer passing mechanism to pass the
serialized IMA binary_runtime_measurements to the next kernel.

Changelog v2:
- Fix build issue by defining a stub ima_add_kexec_buffer and stub
  struct kimage when CONFIG_IMA=n and CONFIG_IMA_KEXEC=n. (Fenguang Wu)
- removed kexec_add_handover_buffer() checksum argument.
- added skip_checksum member to kexec_buf
- only register reboot notifier once

Changelog v1:
- updated to call IMA functions  (Mimi)
- move code from ima_template.c to ima_kexec.c (Mimi)

Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/ima.h| 12 ++
 kernel/kexec_file.c|  4 ++
 security/integrity/ima/ima_kexec.c | 88 ++
 3 files changed, 104 insertions(+)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 0eb7c2e..7f6952f 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -11,6 +11,7 @@
 #define _LINUX_IMA_H
 
 #include 
+#include 
 struct linux_binprm;
 
 #ifdef CONFIG_IMA
@@ -23,6 +24,10 @@ extern int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
  enum kernel_read_file_id id);
 extern void ima_post_path_mknod(struct dentry *dentry);
 
+#ifdef CONFIG_IMA_KEXEC
+extern void ima_add_kexec_buffer(struct kimage *image);
+#endif
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
@@ -62,6 +67,13 @@ static inline void ima_post_path_mknod(struct dentry *dentry)
 
 #endif /* CONFIG_IMA */
 
+#ifndef CONFIG_IMA_KEXEC
+struct kimage;
+
+static inline void ima_add_kexec_buffer(struct kimage *image)
+{}
+#endif
+
 #ifdef CONFIG_IMA_APPRAISE
 extern void ima_inode_post_setattr(struct dentry *dentry);
 extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 0e90d14..9585861 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -200,6 +201,9 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
return ret;
image->kernel_buf_len = size;
 
+   /* IMA needs to pass the measurement list to the next kernel. */
+   ima_add_kexec_buffer(image);
+
/* Call arch image probe handlers */
ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
image->kernel_buf_len);
diff --git a/security/integrity/ima/ima_kexec.c 
b/security/integrity/ima/ima_kexec.c
index e77ca9d..0e4d0db 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -23,6 +23,11 @@
 
 #include "ima.h"
 
+#ifdef CONFIG_IMA_KEXEC
+/* Physical address of the measurement buffer in the next kernel. */
+static unsigned long kexec_buffer_load_addr;
+static size_t kexec_segment_size;
+
 static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 unsigned long segment_size)
 {
@@ -75,6 +80,89 @@ out:
 }
 
 /*
+ * Called during kexec execute so that IMA can save the measurement list.
+ */
+static int ima_update_kexec_buffer(struct notifier_block *self,
+  unsigned long action, void *data)
+{
+   void *kexec_buffer = NULL;
+   size_t kexec_buffer_size;
+   int ret;
+
+   if (!kexec_in_progress)
+   return NOTIFY_OK;
+
+   kexec_buffer_size = ima_get_binary_runtime_size();
+   if (kexec_buffer_size >
+   (kexec_segment_size - sizeof(struct ima_kexec_hdr))) {
+   pr_err("Binary measurement list grew too large.\n");
+   goto out;
+   }
+
+   ima_dump_measurement_list(_buffer_size, _buffer,
+ kexec_segment_size);
+   if (!kexec_buffer) {
+   pr_err("Not enough memory for the kexec measurement buffer.\n");
+   goto out;
+   }
+   ret = kexec_update_segment(kexec_buffer, kexec_buffer_size,
+  kexec_buffer_load_addr, kexec_segment_size);
+   if (ret)
+   pr_err("Error updating kexec buffer: %d\n", ret);
+out:
+   return NOTIFY_OK;
+}
+
+struct notifier_block update_buffer_nb = {
+   .notifier_call = ima_update_kexec_buffer,
+};
+
+/*
+ * Called during kexec_file_load so that IMA can add a segment to the kexec
+ * image for the measurement list for the next kernel.
+ */
+void ima_add_kexec_buffer(struct kimage *image)
+{
+   static int registered = 0;
+   struct kexec_buf kbuf = { .image = image, .buf_align = PAGE_SIZE,
+ .buf_min = 0, .buf_max = ULONG_MAX,
+ 

[PATHC v2 2/9] ima: permit duplicate measurement list entries

2016-08-30 Thread Mimi Zohar
Measurements carried across kexec need to be added to the IMA
measurement list, but should not prevent measurements of the newly
booted kernel from being added to the measurement list. This patch
adds support for allowing duplicate measurements.

The "boot_aggregate" measurement entry is the delimiter between soft
boots.

Signed-off-by: Mimi Zohar <zo...@linuv.vnet.ibm.com>
---
 security/integrity/ima/ima_queue.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_queue.c 
b/security/integrity/ima/ima_queue.c
index 4b1bb77..12d1b04 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -65,11 +65,12 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 
*digest_value,
 }
 
 /* ima_add_template_entry helper function:
- * - Add template entry to measurement list and hash table.
+ * - Add template entry to the measurement list and hash table, for
+ *   all entries except those carried across kexec.
  *
  * (Called with ima_extend_list_mutex held.)
  */
-static int ima_add_digest_entry(struct ima_template_entry *entry)
+static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
 {
struct ima_queue_entry *qe;
unsigned int key;
@@ -85,8 +86,10 @@ static int ima_add_digest_entry(struct ima_template_entry 
*entry)
list_add_tail_rcu(>later, _measurements);
 
atomic_long_inc(_htable.len);
-   key = ima_hash_key(entry->digest);
-   hlist_add_head_rcu(>hnext, _htable.queue[key]);
+   if (flags) {
+   key = ima_hash_key(entry->digest);
+   hlist_add_head_rcu(>hnext, _htable.queue[key]);
+   }
return 0;
 }
 
@@ -126,7 +129,7 @@ int ima_add_template_entry(struct ima_template_entry 
*entry, int violation,
}
}
 
-   result = ima_add_digest_entry(entry);
+   result = ima_add_digest_entry(entry, 1);
if (result < 0) {
audit_cause = "ENOMEM";
audit_info = 0;
@@ -155,7 +158,7 @@ int ima_restore_measurement_entry(struct ima_template_entry 
*entry)
int result = 0;
 
mutex_lock(_extend_list_mutex);
-   result = ima_add_digest_entry(entry);
+   result = ima_add_digest_entry(entry, 0);
mutex_unlock(_extend_list_mutex);
return result;
 }
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 0/5] kexec_file: Add buffer hand-over for the next kernel

2016-08-27 Thread Mimi Zohar
On Thu, 2016-08-25 at 19:17 -0300, Thiago Jung Bauermann wrote:
> Am Donnerstag, 25 August 2016, 14:12:43 schrieb Andrew Morton:
> > I grabbed these two patch series.  I also merged the "IMA:
> > Demonstration code for kexec buffer passing." demonstration patch just
> > to get things a bit of testing.
> 
> Thank you very much!

Thank you, Andrew.

> > I assume that once the "ima: carry the
> > measurement list across kexec" series has stabilised, I should drop the
> > demo patch and also grab those?  If so, pelase start cc'ing me.
> 
> I'm not sure how Mimi is planning to upstream that series.

I'll re-post the patches shortly, cc'ing you.  It will contain support
for saving the binary measurement list on one architecture (eg. little
endian) and restoring it on another (eg. big endian).

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH 1/7] ima: on soft reboot, restore the measurement list

2016-08-10 Thread Mimi Zohar
On Wed, 2016-08-10 at 19:52 +1000, Michael Ellerman wrote:
> Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com> writes:
> 
> > Am Mittwoch, 10 August 2016, 13:41:08 schrieb Michael Ellerman:
> >> Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com> writes:
> >> > Am Dienstag, 09 August 2016, 09:01:13 schrieb Mimi Zohar:
> >> >> On Tue, 2016-08-09 at 20:59 +1000, Michael Ellerman wrote:
> >> >> > Mimi Zohar <zo...@linux.vnet.ibm.com> writes: 
> >> >> > > +/* Some details preceding the binary serialized measurement list
> >> >> > > */
> >> >> > > +struct ima_kexec_hdr {
> >> >> > > +   unsigned short version;
> >> >> > > +   unsigned long buffer_size;
> >> >> > > +   unsigned long count;
> >> >> > > +} __packed;
> >> >> > > +
> >> >> > 
> >> >> > Am I understanding it correctly that this structure is passed between
> >> >> > kernels?
> >> >> 
> >> >> Yes, the header prefixes the measurement list, which is being passed on
> >> >> the same computer to the next kernel.  Could the architecture (eg.
> >> >> LE/BE) change between soft re-boots?
> >> > 
> >> > Yes. I am able to boot a BE kernel from an LE kernel with my patches.
> >> > Whether we want to support that or not is another question...
> >> 
> >> Yes you must support that. BE -> LE and vice versa.
> >
> > I didn't test BE - LE yet, but will do.
> 
> Thanks.

Ok. There have been requests for making the binary_runtime_measurements
architecture independent.  As this was not a network facing interface,
we left it in native format.  With the kernel now consuming this data,
it makes sense for the binary_runtime_measurements to be in an
architecture independent format.

Unfortunately, as the /ima/binary_runtime_measurements is
not prefixed with any metadata, this change would need to be Kconfig
based, but kexec would always use the architecture independent format.

> >> You should also consider the possibility that the next kernel is not
> >> Linux.

Oh!

> > If the next kernel is an ELF binary and it supports the kexec "calling 
> > convention", it should work too. What could possibly go wrong? I can try 
> > FreeBSD (I suppose it's an ELF kernel) and see what happens.
> 
> At least for old style kexec (not sys_kexec_load()) I don't think it
> even needs to be an ELF binary.
> 
> I think there are folks working on FreeBSD (or $?BSD), so I think the
> basic kexec part works.
> 
> There's nothing (yet) that wants to use this measurement list obviously,
> but it should be designed such that it could be used by an unknown
> future kernel that knows the ABI.
> 
> So given what you have above, you'd use something like:
> 
> struct ima_kexec_hdr {
>   u16 version;
>   u16 _reserved0;
>   u32 _reserved1;
>   u64 buffer_size;
>   u64 count;
> };
> 
> cheers

Thanks, I'll make this change.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH 1/7] ima: on soft reboot, restore the measurement list

2016-08-09 Thread Mimi Zohar
On Tue, 2016-08-09 at 09:55 -0400, Mimi Zohar wrote:
> On Tue, 2016-08-09 at 10:19 -0300, Thiago Jung Bauermann wrote:
> > Am Dienstag, 09 August 2016, 09:01:13 schrieb Mimi Zohar:
> > > On Tue, 2016-08-09 at 20:59 +1000, Michael Ellerman wrote:
> > > > Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> > > > > diff --git a/security/integrity/ima/ima.h
> > > > > b/security/integrity/ima/ima.h
> > > > > index b5728da..84e8d36 100644
> > > > > --- a/security/integrity/ima/ima.h
> > > > > +++ b/security/integrity/ima/ima.h
> > > > > @@ -102,6 +102,13 @@ struct ima_queue_entry {
> > > > > 
> > > > >  };
> > > > >  extern struct list_head ima_measurements;/* list of all 
> > measurements
> > > > >  */
> > > > > 
> > > > > +/* Some details preceding the binary serialized measurement list */
> > > > > +struct ima_kexec_hdr {
> > > > > + unsigned short version;
> > > > > + unsigned long buffer_size;
> > > > > + unsigned long count;
> > > > > +} __packed;
> > > > > +
> > > > 
> > > > Am I understanding it correctly that this structure is passed between
> > > > kernels?
> > > Yes, the header prefixes the measurement list, which is being passed on
> > > the same computer to the next kernel.  Could the architecture (eg.
> > > LE/BE) change between soft re-boots?
> > 
> > Yes. I am able to boot a BE kernel from an LE kernel with my patches. 
> > Whether we want to support that or not is another question...
> 
> The  dependent.  It looks like the khdr->version check in
> ima_restore_measurement_list() would fail if the architecture changes.
> 
> If/when we update the binary measurement list format to support multiple
> TPM PCRs, we should address the endianness as well.

That should have been "TPM PCR banks".  TPM 2.0 allows for multiple TPM
PCR banks.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH 1/7] ima: on soft reboot, restore the measurement list

2016-08-09 Thread Mimi Zohar
On Tue, 2016-08-09 at 10:19 -0300, Thiago Jung Bauermann wrote:
> Am Dienstag, 09 August 2016, 09:01:13 schrieb Mimi Zohar:
> > On Tue, 2016-08-09 at 20:59 +1000, Michael Ellerman wrote:
> > > Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> > > > diff --git a/security/integrity/ima/ima.h
> > > > b/security/integrity/ima/ima.h
> > > > index b5728da..84e8d36 100644
> > > > --- a/security/integrity/ima/ima.h
> > > > +++ b/security/integrity/ima/ima.h
> > > > @@ -102,6 +102,13 @@ struct ima_queue_entry {
> > > > 
> > > >  };
> > > >  extern struct list_head ima_measurements;  /* list of all 
> measurements
> > > >  */
> > > > 
> > > > +/* Some details preceding the binary serialized measurement list */
> > > > +struct ima_kexec_hdr {
> > > > +   unsigned short version;
> > > > +   unsigned long buffer_size;
> > > > +   unsigned long count;
> > > > +} __packed;
> > > > +
> > > 
> > > Am I understanding it correctly that this structure is passed between
> > > kernels?
> > Yes, the header prefixes the measurement list, which is being passed on
> > the same computer to the next kernel.  Could the architecture (eg.
> > LE/BE) change between soft re-boots?
> 
> Yes. I am able to boot a BE kernel from an LE kernel with my patches. 
> Whether we want to support that or not is another question...

The version check in
ima_restore_measurement_list() would fail if the architecture changes.

If/when we update the binary measurement list format to support multiple
TPM PCRs, we should address the endianness as well.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH 1/7] ima: on soft reboot, restore the measurement list

2016-08-09 Thread Mimi Zohar
On Tue, 2016-08-09 at 20:59 +1000, Michael Ellerman wrote:
> Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> 
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index b5728da..84e8d36 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -102,6 +102,13 @@ struct ima_queue_entry {
> >  };
> >  extern struct list_head ima_measurements;  /* list of all measurements */
> >  
> > +/* Some details preceding the binary serialized measurement list */
> > +struct ima_kexec_hdr {
> > +   unsigned short version;
> > +   unsigned long buffer_size;
> > +   unsigned long count;
> > +} __packed;
> > +
> 
> Am I understanding it correctly that this structure is passed between kernels?

Yes, the header prefixes the measurement list, which is being passed on
the same computer to the next kernel.  Could the architecture (eg.
LE/BE) change between soft re-boots?

> If so it's an ABI and should use types with well defined sizes, as if it was
> going out to userspace, shouldn't it?

Ok

Mimi



___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH 1/7] ima: on soft reboot, restore the measurement list

2016-08-05 Thread Mimi Zohar
Hi Petko,

Thank you for review!

On Fri, 2016-08-05 at 11:44 +0300, Petko Manolov wrote:
> On 16-08-04 08:24:29, Mimi Zohar wrote:
> > The TPM PCRs are only reset on a hard reboot.  In order to validate a
> > TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
> > of the running kernel must be saved and restored on boot.  This patch
> > restores the measurement list.
> > 
> > Changelog:
> > - call ima_load_kexec_buffer() (Thiago)
> > 
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> > ---
> >  security/integrity/ima/Makefile   |   1 +
> >  security/integrity/ima/ima.h  |  10 ++
> >  security/integrity/ima/ima_init.c |   2 +
> >  security/integrity/ima/ima_kexec.c|  55 +++
> >  security/integrity/ima/ima_queue.c|  10 ++
> >  security/integrity/ima/ima_template.c | 171 
> > ++
> >  6 files changed, 249 insertions(+)
> >  create mode 100644 security/integrity/ima/ima_kexec.c
> > 
> > diff --git a/security/integrity/ima/Makefile 
> > b/security/integrity/ima/Makefile
> > index c34599f..c0ce7b1 100644
> > --- a/security/integrity/ima/Makefile
> > +++ b/security/integrity/ima/Makefile
> > @@ -8,4 +8,5 @@ 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_buffer.o
> >  ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
> > +ima-$(CONFIG_KEXEC_FILE) += ima_kexec.o
> >  obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index b5728da..84e8d36 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -102,6 +102,13 @@ struct ima_queue_entry {
> >  };
> >  extern struct list_head ima_measurements;  /* list of all measurements */
> >  
> > +/* Some details preceding the binary serialized measurement list */
> > +struct ima_kexec_hdr {
> > +   unsigned short version;
> > +   unsigned long buffer_size;
> > +   unsigned long count;
> > +} __packed;
> 
> Unless there is no real need for this structure to be packed i suggest 
> dropping 
> the attribute.  When referenced through pointer 32bit ARM and MIPS (and 
> likely 
> all other 32bit RISC CPUs) use rather inefficient byte loads and stores.
> 
> Worse, if, for example, ->count is going to be read/written concurrently from 
> multiple threads we get torn loads/stores thus losing atomicity of the access.

This header is used to prefix the serialized binary measurement list
with some meta-data about the measurement list being restored.
Unfortunately kexec_get_handover_buffer() returns the segment size, not
the actual ima measurement list buffer size.  The header info is set
using memcpy() once in ima_dump_measurement_list() and then the fields
are used in ima_restore_measurement_list() to verify the buffer.

The binary runtime measurement list is packed, so the other two
structures - binary_hdr_v1 and binary_data_v1 - must be packed.  Does it
make sense for this header not to be packed as well?  Would copying the
header fields to local variables before being used solve your concern?

Remember this code is used once on the kexec execute and again on
reboot.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH 6/7] ima: store the builtin/custom template definitions in a list

2016-08-04 Thread Mimi Zohar
The builtin and single custom templates are currently stored in an
array.  In preparation for being able to restore a measurement list
containing multiple builtin/custom templates, this patch stores the
builtin and custom templates as a linked list.  This will permit
defining more than one custom template per boot.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h  |  2 ++
 security/integrity/ima/ima_main.c |  1 +
 security/integrity/ima/ima_template.c | 37 +++
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index f972296..9d7fdd5 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -81,6 +81,7 @@ struct ima_template_field {
 
 /* IMA template descriptor definition */
 struct ima_template_desc {
+   struct list_head list;
char *name;
char *fmt;
int num_fields;
@@ -135,6 +136,7 @@ int ima_restore_measurement_list(loff_t bufsize, void *buf);
 int ima_measurements_show(struct seq_file *m, void *v);
 unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
+void ima_init_template_list(void);
 
 /*
  * used to protect h_table and sha_table
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index 596ef61..592f318 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -418,6 +418,7 @@ static int __init init_ima(void)
 {
int error;
 
+   ima_init_template_list();
hash_setup(CONFIG_IMA_DEFAULT_HASH);
error = ima_init();
if (!error) {
diff --git a/security/integrity/ima/ima_template.c 
b/security/integrity/ima/ima_template.c
index c6510f0..b7bcb62 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -15,16 +15,20 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include "ima.h"
 #include "ima_template_lib.h"
 
-static struct ima_template_desc defined_templates[] = {
+static struct ima_template_desc builtin_templates[] = {
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
{.name = "ima-ng", .fmt = "d-ng|n-ng"},
{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
{.name = "", .fmt = ""},/* placeholder for a custom format */
 };
 
+static LIST_HEAD(defined_templates);
+spinlock_t template_list;
+
 static struct ima_template_field supported_fields[] = {
{.field_id = "d", .field_init = ima_eventdigest_init,
 .field_show = ima_show_template_digest},
@@ -80,7 +84,7 @@ __setup("ima_template=", ima_template_setup);
 
 static int __init ima_template_fmt_setup(char *str)
 {
-   int num_templates = ARRAY_SIZE(defined_templates);
+   int num_templates = ARRAY_SIZE(builtin_templates);
 
if (ima_template)
return 1;
@@ -91,20 +95,24 @@ static int __init ima_template_fmt_setup(char *str)
return 1;
}
 
-   defined_templates[num_templates - 1].fmt = str;
-   ima_template = defined_templates + num_templates - 1;
+   builtin_templates[num_templates - 1].fmt = str;
+   ima_template = builtin_templates + num_templates - 1;
+
return 1;
 }
 __setup("ima_template_fmt=", ima_template_fmt_setup);
 
 static struct ima_template_desc *lookup_template_desc(const char *name)
 {
-   int i;
+   struct ima_template_desc *template_desc;
 
-   for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
-   if (strcmp(defined_templates[i].name, name) == 0)
-   return defined_templates + i;
+   rcu_read_lock();
+   list_for_each_entry_rcu(template_desc, _templates, list) {
+   if ((strcmp(template_desc->name, name) == 0) ||
+   (strcmp(template_desc->fmt, name) == 0))
+   return template_desc;
}
+   rcu_read_unlock();
 
return NULL;
 }
@@ -190,6 +198,19 @@ struct ima_template_desc *ima_template_desc_current(void)
return ima_template;
 }
 
+void __init ima_init_template_list(void)
+{
+   int i;
+
+   spin_lock(_list);
+   for (i = 0; i < ARRAY_SIZE(builtin_templates); i++) {
+   list_add_tail_rcu(_templates[i].list,
+ _templates);
+   }
+   spin_unlock(_list);
+   synchronize_rcu();
+}
+
 int __init ima_init_template(void)
 {
struct ima_template_desc *template = ima_template_desc_current();
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH 3/7] ima: maintain memory size needed for serializing the measurement list

2016-08-04 Thread Mimi Zohar
In preparation for serializing the binary_runtime_measurements, this patch
maintains the amount of memory required.

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

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 0fb54d3..d764027 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 && KEXEC_FILE
+   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 84e8d36..222668f 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -132,6 +132,7 @@ struct ima_template_desc *ima_template_desc_current(void);
 void ima_load_kexec_buffer(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 12d1b04..8f0661b 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,26 @@ static int ima_add_digest_entry(struct ima_template_entry 
*entry, int flags)
key = ima_hash_key(entry->digest);
hlist_add_head_rcu(>hnext, _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.
+ */
+unsigned long ima_get_binary_runtime_size(void)
+{
+   return binary_runtime_size;
+};
+
 static int ima_pcr_extend(const u8 *hash, int pcr)
 {
int result = 0;
@@ -106,8 +146,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.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH 5/7] ima: on soft reboot, save the measurement list

2016-08-04 Thread Mimi Zohar
From: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

This patch uses the kexec buffer passing mechanism to pass the
serialized IMA binary_runtime_measurements to the next kernel.

Changelog:
- updated to call IMA functions  (Mimi)
- move code from ima_template.c to ima_kexec.c (Mimi)

Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/ima.h| 15 +++
 kernel/kexec_file.c|  3 ++
 security/integrity/ima/ima_kexec.c | 83 ++
 3 files changed, 101 insertions(+)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index b553367..ba484ed 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -11,6 +11,7 @@
 #define _LINUX_IMA_H
 
 #include 
+#include 
 struct linux_binprm;
 
 enum ima_buffer_id {
@@ -35,6 +36,14 @@ extern int ima_add_measurement_check(const char *hashname, 
u8 *digest,
 loff_t size, enum ima_buffer_id buffer_id,
 char *hint);
 
+#ifdef CONFIG_IMA_KEXEC
+extern void ima_add_kexec_buffer(struct kimage *image);
+#else
+static inline void ima_add_kexec_buffer(struct kimage *image)
+{
+}
+#endif
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
@@ -85,6 +94,12 @@ static inline int ima_add_measurement_check(const char 
*hashname, u8 *digest,
 {
return 0;
 }
+
+#ifdef CONFIG_IMA_KEXEC
+static inline void ima_add_kexec_buffer(struct kimage *image)
+{
+}
+#endif
 #endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 852adb2..622c126 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -202,6 +202,9 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
return ret;
image->kernel_buf_len = size;
 
+   /* IMA needs to pass the measurement list to the next kernel. */
+   ima_add_kexec_buffer(image);
+
/* Call arch image probe handlers */
ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
image->kernel_buf_len);
diff --git a/security/integrity/ima/ima_kexec.c 
b/security/integrity/ima/ima_kexec.c
index e77ca9d..3fed417 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -23,6 +23,11 @@
 
 #include "ima.h"
 
+#ifdef CONFIG_IMA_KEXEC
+/* Physical address of the measurement buffer in the next kernel. */
+static unsigned long kexec_buffer_load_addr;
+static size_t kexec_segment_size;
+
 static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 unsigned long segment_size)
 {
@@ -75,6 +80,84 @@ out:
 }
 
 /*
+ * Called during kexec execute so that IMA can save the measurement list.
+ */
+static int ima_update_kexec_buffer(struct notifier_block *self,
+  unsigned long action, void *data)
+{
+   void *kexec_buffer = NULL;
+   size_t kexec_buffer_size;
+   int ret;
+
+   if (!kexec_in_progress)
+   return NOTIFY_OK;
+
+   kexec_buffer_size = ima_get_binary_runtime_size();
+   if (kexec_buffer_size >
+   (kexec_segment_size - sizeof(struct ima_kexec_hdr))) {
+   pr_err("Binary measurement list grew too large.\n");
+   goto out;
+   }
+
+   ima_dump_measurement_list(_buffer_size, _buffer,
+ kexec_segment_size);
+   if (!kexec_buffer) {
+   pr_err("Not enough memory for the kexec measurement buffer.\n");
+   goto out;
+   }
+   ret = kexec_update_segment(kexec_buffer, kexec_buffer_size,
+  kexec_buffer_load_addr, kexec_segment_size);
+   if (ret)
+   pr_err("Error updating kexec buffer: %d\n", ret);
+out:
+   return NOTIFY_OK;
+}
+
+struct notifier_block update_buffer_nb = {
+   .notifier_call = ima_update_kexec_buffer,
+};
+
+/*
+ * Called during kexec_file_load so that IMA can add a segment to the kexec
+ * image for the measurement list for the next kernel.
+ */
+void ima_add_kexec_buffer(struct kimage *image)
+{
+   struct kexec_buf kbuf = { .image = image, .buf_align = PAGE_SIZE,
+ .buf_min = 0, .buf_max = ULONG_MAX,
+ .top_down = true };
+   int ret;
+
+   if (!kexec_can_hand_over_buffer())
+   return;
+
+   kexec_segment_size = ALIGN(ima_get_binary_runtime_size() + PAGE_SIZE,
+  PAGE_SIZE);
+
+   if (kexec_segment_size >= (ULONG_MAX - sizeof(long))) {
+   pr_err("Binary measurement list too large.\n");
+   return;
+   }
+
+   /* Ask not to checksum the segment, we will update 

[PATCH 0/7] ima: carry the measurement list across kexec

2016-08-04 Thread Mimi Zohar
The TPM PCRs are only reset on a hard reboot.  In order to validate a
TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
of the running kernel must be saved and then restored on the subsequent
boot.

The existing securityfs binary_runtime_measurements file conveniently
provides a serialized format of the IMA measurement list. This patch
set serializes the measurement list in this format and restores it.

This patch set pre-req's Thiago Bauermann's "kexec_file: Add buffer
hand-over for the next kernel" patch set* for actually carrying the
serialized measurement list across the kexec.

Mimi

*https://lists.infradead.org/pipermail/kexec/2016-June/016157.html

Mimi Zohar (6):
  ima: on soft reboot, restore the measurement list
  ima: permit duplicate measurement list entries
  ima: maintain memory size needed for serializing the measurement list
  ima: serialize the binary_runtime_measurements
  ima: store the builtin/custom template definitions in a list
  ima: support restoring multiple template formats

Thiago Jung Bauermann (1):
  ima: on soft reboot, save the measurement list

 include/linux/ima.h   |  15 ++
 kernel/kexec_file.c   |   3 +
 security/integrity/ima/Kconfig|  12 ++
 security/integrity/ima/Makefile   |   1 +
 security/integrity/ima/ima.h  |  14 ++
 security/integrity/ima/ima_fs.c   |   2 +-
 security/integrity/ima/ima_init.c |   2 +
 security/integrity/ima/ima_kexec.c| 189 
 security/integrity/ima/ima_main.c |   1 +
 security/integrity/ima/ima_queue.c|  72 +-
 security/integrity/ima/ima_template.c | 262 --
 11 files changed, 556 insertions(+), 17 deletions(-)
 create mode 100644 security/integrity/ima/ima_kexec.c

-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH 2/7] ima: permit duplicate measurement list entries

2016-08-04 Thread Mimi Zohar
Measurements carried across kexec need to be added to the IMA
measurement list, but should not prevent measurements of the newly
booted kernel from being added to the measurement list. This patch
adds support for allowing duplicate measurements.

The "boot_aggregate" measurement entry is the delimiter between soft
boots.

Signed-off-by: Mimi Zohar <zo...@linuv.vnet.ibm.com>
---
 security/integrity/ima/ima_queue.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_queue.c 
b/security/integrity/ima/ima_queue.c
index 4b1bb77..12d1b04 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -65,11 +65,12 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 
*digest_value,
 }
 
 /* ima_add_template_entry helper function:
- * - Add template entry to measurement list and hash table.
+ * - Add template entry to the measurement list and hash table, for
+ *   all entries except those carried across kexec.
  *
  * (Called with ima_extend_list_mutex held.)
  */
-static int ima_add_digest_entry(struct ima_template_entry *entry)
+static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
 {
struct ima_queue_entry *qe;
unsigned int key;
@@ -85,8 +86,10 @@ static int ima_add_digest_entry(struct ima_template_entry 
*entry)
list_add_tail_rcu(>later, _measurements);
 
atomic_long_inc(_htable.len);
-   key = ima_hash_key(entry->digest);
-   hlist_add_head_rcu(>hnext, _htable.queue[key]);
+   if (flags) {
+   key = ima_hash_key(entry->digest);
+   hlist_add_head_rcu(>hnext, _htable.queue[key]);
+   }
return 0;
 }
 
@@ -126,7 +129,7 @@ int ima_add_template_entry(struct ima_template_entry 
*entry, int violation,
}
}
 
-   result = ima_add_digest_entry(entry);
+   result = ima_add_digest_entry(entry, 1);
if (result < 0) {
audit_cause = "ENOMEM";
audit_info = 0;
@@ -155,7 +158,7 @@ int ima_restore_measurement_entry(struct ima_template_entry 
*entry)
int result = 0;
 
mutex_lock(_extend_list_mutex);
-   result = ima_add_digest_entry(entry);
+   result = ima_add_digest_entry(entry, 0);
mutex_unlock(_extend_list_mutex);
return result;
 }
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH 4/7] ima: serialize the binary_runtime_measurements

2016-08-04 Thread Mimi Zohar
The TPM PCRs are only reset on a hard reboot.  In order to validate a
TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
of the running kernel must be saved and restored on boot.  This patch
serializes the IMA measurement list in the binary_runtime_measurements
format.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h   |  1 +
 security/integrity/ima/ima_fs.c|  2 +-
 security/integrity/ima/ima_kexec.c | 51 ++
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 222668f..f972296 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -132,6 +132,7 @@ struct ima_template_desc *ima_template_desc_current(void);
 void ima_load_kexec_buffer(void);
 int ima_restore_measurement_entry(struct ima_template_entry *entry);
 int ima_restore_measurement_list(loff_t bufsize, void *buf);
+int ima_measurements_show(struct seq_file *m, void *v);
 unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
 
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index c07a384..66e5dd5 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -116,7 +116,7 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
  *   [eventdata length]
  *   eventdata[n]=template specific data
  */
-static int ima_measurements_show(struct seq_file *m, void *v)
+int ima_measurements_show(struct seq_file *m, void *v)
 {
/* the list never shrinks, so we don't need a lock here */
struct ima_queue_entry *qe = v;
diff --git a/security/integrity/ima/ima_kexec.c 
b/security/integrity/ima/ima_kexec.c
index 6a046ad..e77ca9d 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -23,6 +23,57 @@
 
 #include "ima.h"
 
+static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
+unsigned long segment_size)
+{
+   struct ima_queue_entry *qe;
+   struct seq_file file;
+   struct ima_kexec_hdr khdr = {
+   .version = 1, .buffer_size = 0, .count = 0};
+   int ret = 0;
+
+   /* segment size can't change between kexec load and execute */
+   file.buf = vmalloc(segment_size);
+   if (!file.buf) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   file.size = segment_size;
+   file.read_pos = 0;
+   file.count = sizeof(khdr);  /* reserved space */
+
+   list_for_each_entry_rcu(qe, _measurements, later) {
+   if (file.count < file.size) {
+   khdr.count++;
+   ima_measurements_show(, qe);
+   } else {
+   ret = -EINVAL;
+   break;
+   }
+   }
+
+   if (ret < 0)
+   goto out;
+
+   /*
+* fill in reserved space with some buffer details
+* (eg. version, buffer size, number of measurements)
+*/
+   khdr.buffer_size = file.count;
+   memcpy(file.buf, , sizeof(khdr));
+   print_hex_dump(KERN_DEBUG, "ima dump: ", DUMP_PREFIX_NONE,
+   16, 1, file.buf,
+   file.count < 100 ? file.count : 100, true);
+
+   *buffer_size = file.count;
+   *buffer = file.buf;
+out:
+   if (ret == -EINVAL)
+   vfree(file.buf);
+   return ret;
+}
+
 /*
  * Restore the measurement list from the previous kernel.
  */
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH 3/3] ima: add pre-calculated measurements (experimental)

2016-06-22 Thread Mimi Zohar
This patch defines a new IMA hook named ima_add_measurement_check()
for including pre-calculated measurements in the IMA measurement list.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 Documentation/ABI/testing/ima_policy |   2 +-
 include/linux/ima.h  |  12 
 security/integrity/ima/Kconfig   |   8 +++
 security/integrity/ima/ima.h |   1 +
 security/integrity/ima/ima_buffer.c  | 116 +--
 security/integrity/ima/ima_policy.c  |  18 +-
 6 files changed, 136 insertions(+), 21 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 5a99c6f..e5a137e 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -28,7 +28,7 @@ Description:
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
-   [KEXEC_CMDLINE_CHECK]
+   [KEXEC_CMDLINE_CHECK] [PRECALC_CHECK]
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
   [[^]MAY_EXEC]
fsmagic:= hex value
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 88203f9..797de51 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -15,6 +15,7 @@ struct linux_binprm;
 
 enum ima_buffer_id {
MEASURING_KEXEC_CMDLINE,
+   MEASURING_PRECALC_DATA,
MEASURING_MAX_BUFFER_ID
 };
 
@@ -29,6 +30,9 @@ extern int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
 extern void ima_post_path_mknod(struct dentry *dentry);
 extern void ima_buffer_check(void *buf, loff_t size,
 enum ima_buffer_id buffer_id);
+extern void ima_add_measurement_check(const char *hashname, u8 *digest,
+ loff_t size, enum ima_buffer_id buffer_id,
+ char *hint);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -72,6 +76,14 @@ static inline void ima_buffer_check(void *buf, loff_t size,
 {
return;
 }
+
+static inline void ima_add_measurement_check(const char *hashname, u8 *digest,
+loff_t size,
+enum ima_buffer_id buffer_id,
+char *hint)
+{
+   return;
+}
 #endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 5487827..0fb54d3 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -44,6 +44,14 @@ config IMA_LSM_RULES
help
  Disabling this option will disregard LSM based policy rules.
 
+config IMA_PRECALC_RULES
+   bool "Permit pre-calculated measurements (EXPERIMENTAL)"
+   depends on IMA
+   default n
+   help
+ Enabling this option will permit pre-calculated measurements
+ to be added to the IMA measurement list.
+
 choice
prompt "Default template"
default IMA_NG_TEMPLATE
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 5f21a9a..ccad21d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -152,6 +152,7 @@ enum ima_hooks {
KEXEC_INITRAMFS_CHECK,
KEXEC_CMDLINE_CHECK,
POLICY_CHECK,
+   PRECALC_CHECK,
MAX_CHECK
 };
 
diff --git a/security/integrity/ima/ima_buffer.c 
b/security/integrity/ima/ima_buffer.c
index e74131b..ad49f6c 100644
--- a/security/integrity/ima/ima_buffer.c
+++ b/security/integrity/ima/ima_buffer.c
@@ -11,6 +11,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "ima.h"
 
@@ -21,9 +23,37 @@ struct buffer_idmap {
 
 static struct buffer_idmap _idmap[MEASURING_MAX_BUFFER_ID] = {
[MEASURING_KEXEC_CMDLINE].func = KEXEC_CMDLINE_CHECK,
-   [MEASURING_KEXEC_CMDLINE].buf = "boot-cmdline",
+   [MEASURING_KEXEC_CMDLINE].buf = "kexec-boot-cmdline",
+   [MEASURING_PRECALC_DATA].func = PRECALC_CHECK,
+   [MEASURING_PRECALC_DATA].buf = "precalc",
 };
 
+#define IMA_MAX_BUFFER_HINT_SIZE 255
+
+static int store_buffer_measurement(struct ima_digest_data *hash, int pcr,
+   char *buffer_hint)
+{
+   struct ima_template_entry *entry;
+   struct integrity_iint_cache tmp_iint, *iint = _iint;
+   struct ima_event_data event_data = {iint, NULL, NULL, NULL, 0, NULL};
+   int violation = 0;
+   int result;
+
+   iint->ima_hash = hash;
+   event_data.filename = buffer_hint;
+
+   result = ima_alloc_init_template(_data, );
+   if (result < 0)
+   return result;
+
+   result = ima_store_template(entry, viola

[PATCH 1/3] ima: measure other types of data

2016-06-22 Thread Mimi Zohar
In addition to files, other data (eg. boot command line) should be
included in the measurement list to attest to the integrity of a running
system.  A new IMA hook named ima_buffer_check() calculates and includes
the buffer hash in the measurement list.  Callers of this hook provide
the buffer, buffer length and a buffer identifier.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/ima.h | 11 +
 security/integrity/ima/Makefile |  2 +-
 security/integrity/ima/ima.h|  2 +
 security/integrity/ima/ima_buffer.c | 82 +
 security/integrity/ima/ima_policy.c | 26 
 5 files changed, 122 insertions(+), 1 deletion(-)
 create mode 100644 security/integrity/ima/ima_buffer.c

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 0eb7c2e..01319b3 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -13,6 +13,10 @@
 #include 
 struct linux_binprm;
 
+enum ima_buffer_id {
+   MEASURING_MAX_BUFFER_ID
+};
+
 #ifdef CONFIG_IMA
 extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask, int opened);
@@ -22,6 +26,8 @@ extern int ima_read_file(struct file *file, enum 
kernel_read_file_id id);
 extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
  enum kernel_read_file_id id);
 extern void ima_post_path_mknod(struct dentry *dentry);
+extern void ima_buffer_check(void *buf, loff_t size,
+enum ima_buffer_id buffer_id);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -60,6 +66,11 @@ static inline void ima_post_path_mknod(struct dentry *dentry)
return;
 }
 
+static inline void ima_buffer_check(void *buf, loff_t size,
+   enum ima_buffer_id buffer_id)
+{
+   return;
+}
 #endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 9aeaeda..c34599f 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -6,6 +6,6 @@
 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_buffer.o
 ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
 obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index db25f54..cc2e77b 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -154,6 +154,8 @@ enum ima_hooks {
MAX_CHECK
 };
 
+int ima_match_buffer_id(enum ima_hooks func, int *pcr);
+
 /* LIM API function definitions */
 int ima_get_action(struct inode *inode, int mask,
   enum ima_hooks func, int *pcr);
diff --git a/security/integrity/ima/ima_buffer.c 
b/security/integrity/ima/ima_buffer.c
new file mode 100644
index 000..84c9494
--- /dev/null
+++ b/security/integrity/ima/ima_buffer.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar <zo...@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2 of the License.
+ */
+#include 
+#include 
+#include 
+
+#include "ima.h"
+
+struct buffer_idmap {
+   enum ima_hooks func;
+   char *buf;
+};
+
+static struct buffer_idmap _idmap[MEASURING_MAX_BUFFER_ID] = {
+};
+
+static void process_buffer_measurement(void *buf, loff_t size,
+  enum ima_buffer_id buffer_id, int pcr)
+{
+   struct {
+   struct ima_digest_data hdr;
+   char digest[IMA_MAX_DIGEST_SIZE];
+   } hash;
+   struct ima_template_entry *entry;
+   struct integrity_iint_cache tmp_iint, *iint = _iint;
+   struct ima_event_data event_data = {iint, NULL, NULL, NULL, 0, NULL};
+   int violation = 0;
+   int result;
+
+   memset(, 0, sizeof(hash));
+   hash.hdr.algo = ima_hash_algo;
+   result = ima_calc_buffer_hash(buf, size, );
+   if (result < 0) {
+   pr_debug("failed calculating buffer hash\n");
+   return;
+   }
+
+   iint->ima_hash = 
+   event_data.filename = _idmap[buffer_id].buf;
+   result = ima_alloc_init_template(_data, );
+   if (result < 0) {
+   pr_debug("failed allocating template\n");
+   return;
+   }
+
+   result = ima_store_template(entry, violation, NULL,
+   event_data.filename, pcr);
+   if (result < 0) {
+   pr_debug("failed storing buffer measurement\n");
+   ima_free_template_entry(entry);
+   }
+}
+
+/**
+ * ima_buffer_check - based

[PATCH 2/3] kexec: measure boot command line

2016-06-22 Thread Mimi Zohar
This patch defines the buffer identifier "KEXEC_CMDLINE_CHECK" for
measuring the boot command line.

eg: echo -n -e `cat /proc/cmdline | sed 's/^.*root=/root=/'` | sha256sum

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 Documentation/ABI/testing/ima_policy | 1 +
 include/linux/ima.h  | 1 +
 kernel/kexec_file.c  | 4 
 security/integrity/ima/ima.h | 1 +
 security/integrity/ima/ima_buffer.c  | 2 ++
 security/integrity/ima/ima_policy.c  | 9 -
 6 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index bb0f9a1..5a99c6f 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -28,6 +28,7 @@ Description:
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
+   [KEXEC_CMDLINE_CHECK]
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
   [[^]MAY_EXEC]
fsmagic:= hex value
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 01319b3..88203f9 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -14,6 +14,7 @@
 struct linux_binprm;
 
 enum ima_buffer_id {
+   MEASURING_KEXEC_CMDLINE,
MEASURING_MAX_BUFFER_ID
 };
 
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 503bc2d..acc8dad1 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -178,6 +179,9 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
ret = -EINVAL;
goto out;
}
+
+   ima_buffer_check(image->cmdline_buf, cmdline_len - 1,
+MEASURING_KEXEC_CMDLINE);
}
 
/* Call arch image load handlers */
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index cc2e77b..5f21a9a 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -150,6 +150,7 @@ enum ima_hooks {
FIRMWARE_CHECK,
KEXEC_KERNEL_CHECK,
KEXEC_INITRAMFS_CHECK,
+   KEXEC_CMDLINE_CHECK,
POLICY_CHECK,
MAX_CHECK
 };
diff --git a/security/integrity/ima/ima_buffer.c 
b/security/integrity/ima/ima_buffer.c
index 84c9494..e74131b 100644
--- a/security/integrity/ima/ima_buffer.c
+++ b/security/integrity/ima/ima_buffer.c
@@ -20,6 +20,8 @@ struct buffer_idmap {
 };
 
 static struct buffer_idmap _idmap[MEASURING_MAX_BUFFER_ID] = {
+   [MEASURING_KEXEC_CMDLINE].func = KEXEC_CMDLINE_CHECK,
+   [MEASURING_KEXEC_CMDLINE].buf = "boot-cmdline",
 };
 
 static void process_buffer_measurement(void *buf, loff_t size,
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 521d612..8e53f84 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -663,6 +663,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
 == 0)
entry->func = KEXEC_INITRAMFS_CHECK;
+   else if (strcmp(args[0].from, "KEXEC_CMDLINE_CHECK")
+== 0)
+   entry->func = KEXEC_CMDLINE_CHECK;
else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
entry->func = POLICY_CHECK;
else
@@ -926,7 +929,7 @@ enum {
func_file = 0, func_mmap, func_bprm,
func_module, func_firmware, func_post,
func_kexec_kernel, func_kexec_initramfs,
-   func_policy
+   func_kexec_cmdline, func_policy
 };
 
 static char *func_tokens[] = {
@@ -938,6 +941,7 @@ static char *func_tokens[] = {
"POST_SETATTR",
"KEXEC_KERNEL_CHECK",
"KEXEC_INITRAMFS_CHECK",
+   "KEXEC_CMDLINE_CHECK",
"POLICY_CHECK"
 };
 
@@ -1009,6 +1013,9 @@ static void policy_func_show(struct seq_file *m, enum 
ima_hooks func)
case KEXEC_INITRAMFS_CHECK:
seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
break;
+   case KEXEC_CMDLINE_CHECK:
+   seq_printf(m, pt(Opt_func), ft(func_kexec_cmdline));
+   break;
case POLICY_CHECK:
seq_printf(m, pt(Opt_func), ft(func_policy));
break;
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH 0/3] support other types of measurements

2016-06-22 Thread Mimi Zohar
In addition to file measurements, other types of measurements should be
included in the IMA measurement list to attest to the integrity of the
running system.  This patch set introduces two new types of measurements -
buffer and pre-calculated digests.

The first, for example, can be used to measure the kexec boot command
line, while the latter could be used for including asymmetric key id
information.

Mimi Zohar (3):
  ima: measure other types of data
  kexec: measure boot command line
  ima: add pre-calculated measurements (experimental)

 Documentation/ABI/testing/ima_policy |   1 +
 include/linux/ima.h  |  24 +
 kernel/kexec_file.c  |   4 +
 security/integrity/ima/Kconfig   |   8 ++
 security/integrity/ima/Makefile  |   2 +-
 security/integrity/ima/ima.h |   4 +
 security/integrity/ima/ima_buffer.c  | 164 +++
 security/integrity/ima/ima_policy.c  |  51 ++-
 8 files changed, 255 insertions(+), 3 deletions(-)
 create mode 100644 security/integrity/ima/ima_buffer.c
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH 0/6] kexec_file: Add buffer hand-over for the next kernel

2016-06-22 Thread Mimi Zohar
Hi Dave,

On Wed, 2016-06-22 at 09:20 +0800, Dave Young wrote:
> On 06/20/16 at 10:44pm, Thiago Jung Bauermann wrote:
> > Hello,
> > 
> > This patch series implements a mechanism which allows the kernel to pass on
> > a buffer to the kernel that will be kexec'd. This buffer is passed as a
> > segment which is added to the kimage when it is being prepared by
> > kexec_file_load.
> > 
> > How the second kernel is informed of this buffer is architecture-specific.
> > On PowerPC, this is done via the device tree, by checking the properties
> > /chosen/linux,kexec-handover-buffer-start and
> > /chosen/linux,kexec-handover-buffer-end, which is analogous to how the
> > kernel finds the initrd.
> > 
> > This feature was implemented because the Integrity Measurement Architecture
> > subsystem needs to preserve its measurement list accross the kexec reboot.
> > This is so that IMA can implement trusted boot support on the OpenPower
> > platform, because on such systems an intermediary Linux instance running as
> > part of the firmware is used to boot the target operating system via kexec.
> > Using this mechanism, IMA on this intermediary instance can hand over to the
> > target OS the measurements of the components that were used to boot it.
> 
> We have CONFIG_KEXEC_VERIFY_SIG, why not verifying the kernel to be
> loaded instead?  I feel IMA should rebuild its measurement instead of
> passing it to another kernel. Kexec reboot is also a reboot. If we have
> to preserve something get from firmware we can do it, but other than
> that I think it sounds not a good idea.

The signature verification is needed for secure boot.  Carrying the IMA
measurement list across kexec is needed for trusted boot.  In this case,
the boot loader is Linux, which needs to carry the measurements, stored
in memory, across kexec to the target system.

The kernel_read_file_from_fd() calls the pre and post security
kernel_read hooks.  These hooks can verify file signatures, store
measurements in the IMA measurement list and extend the TPM.  To enable
both measuring and appraising (signature verification) of the kernel
image and the initramfs, include the following rules in the IMA policy:

measure func=KEXEC_KERNEL_CHECK
appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig
#
measure func=KEXEC_INITRAMFS_CHECK
appraise func=KEXEC_INITRAMFS_CHECK appraise_type=imasig

Thiago's path set provides the means for carrying the trusted boot
measurements across kexec.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 05/19] vfs: define kernel_read_file_id enumeration

2016-02-12 Thread Mimi Zohar
To differentiate between the kernel_read_file() callers, this patch
defines a new enumeration named kernel_read_file_id and includes the
caller identifier as an argument.

Subsequent patches define READING_KEXEC_IMAGE, READING_KEXEC_INITRAMFS,
READING_FIRMWARE, READING_MODULE, and READING_POLICY.

Changelog v3:
- Replace the IMA specific enumeration with a generic one.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
Cc: Al Viro <v...@zeniv.linux.org.uk>
---
 fs/exec.c | 4 ++--
 include/linux/fs.h| 7 ++-
 include/linux/lsm_hooks.h | 4 +++-
 include/linux/security.h  | 7 +--
 security/security.c   | 5 +++--
 5 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 6b6668b..1138dc5 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -833,7 +833,7 @@ int kernel_read(struct file *file, loff_t offset,
 EXPORT_SYMBOL(kernel_read);
 
 int kernel_read_file(struct file *file, void **buf, loff_t *size,
-loff_t max_size)
+loff_t max_size, enum kernel_read_file_id id)
 {
loff_t i_size, pos;
ssize_t bytes = 0;
@@ -871,7 +871,7 @@ int kernel_read_file(struct file *file, void **buf, loff_t 
*size,
goto out;
}
 
-   ret = security_kernel_post_read_file(file, *buf, i_size);
+   ret = security_kernel_post_read_file(file, *buf, i_size, id);
if (!ret)
*size = pos;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9a83d82..aa84bcb 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2576,8 +2576,13 @@ static inline void i_readcount_inc(struct inode *inode)
 #endif
 extern int do_pipe_flags(int *, int);
 
+enum kernel_read_file_id {
+   READING_MAX_ID
+};
+
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
-extern int kernel_read_file(struct file *, void **, loff_t *, loff_t);
+extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
+   enum kernel_read_file_id);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index f82631c..2337f33 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -567,6 +567,7 @@
  * by the kernel.
  * @buf pointer to buffer containing the file contents.
  * @size length of the file contents.
+ * @id kernel read file identifier
  * Return 0 if permission is granted.
  * @task_fix_setuid:
  * Update the module's state after setting one or more of the user
@@ -1464,7 +1465,8 @@ union security_list_options {
int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file);
-   int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size);
+   int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
+enum kernel_read_file_id id);
int (*task_fix_setuid)(struct cred *new, const struct cred *old,
int flags);
int (*task_setpgid)(struct task_struct *p, pid_t pgid);
diff --git a/include/linux/security.h b/include/linux/security.h
index f30f564..b68ce94 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct linux_binprm;
 struct cred;
@@ -301,7 +302,8 @@ int security_kernel_create_files_as(struct cred *new, 
struct inode *inode);
 int security_kernel_fw_from_file(struct file *file, char *buf, size_t size);
 int security_kernel_module_request(char *kmod_name);
 int security_kernel_module_from_file(struct file *file);
-int security_kernel_post_read_file(struct file *file, char *buf, loff_t size);
+int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
+  enum kernel_read_file_id id);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
 int flags);
 int security_task_setpgid(struct task_struct *p, pid_t pgid);
@@ -868,7 +870,8 @@ static inline int security_kernel_module_from_file(struct 
file *file)
 }
 
 static inline int security_kernel_post_read_file(struct file *file,
-char *buf, loff_t size)
+char *buf, loff_t size,
+enum kernel_read_file_id id)
 {
return 0;
 }
diff --git a/security/security.c b/security/security.c
index ae50730..796a261 100644
--- a/security/security.c
+++ b/security/security.c

[PATCH v4 00/19] vfs: support for a common kernel file loader

2016-02-12 Thread Mimi Zohar
For a while it was looked down upon to directly read files from Linux.
These days there exists a few mechanisms in the kernel that do just this
though to load a file into a local buffer. There are minor but important
checks differences on each, we should take all the best practices from
each of them, generalize them and make all places in the kernel that
read a file use it.[1]

One difference is the method for opening the file.  In some cases we
have a file, while in other cases we have a pathname or a file descriptor.

Another difference is the security hook calls, or lack of them.  In
some versions there is a post file read hook, while in others there
is a pre file read hook. 

This patch set attempts to resolve these differences.  It does not attempt
to merge the different methods of opening a file, but defines a single
common kernel file read function with two wrappers. In addition, as none
of the upstreamed LSMs define either a kernel_module_from_file or a
kernel_fw_from_file hook, this patch set removes these hooks and the
associated functions.  The ima_module_check() and ima_fw_from_file()
functions are renamed and called from the pre and post kernel_read_file
security functions respectively.

Changelog:
- First four IMA patches removed from this patch set.
- Cleaned up the kernel_read_file_id to ima_hooks enumeration mapping.
- Renamed the kexec IMA policy identifiers.
- Added missing include file for other architectures.
- Rebased on top of some of the "firmware_class: extensible firmware API"
patches posted by Luis.
- Removed the kernel_module_from_file and kernel_fw_from_file security
hooks and functions.
- Defined "kernel_read_file_id" enumeration, independently of "ima_hooks".
- Split patches for ease of review.

The latest version of these patches can be found in the next-kernel-read
branch of:
git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git

[1] Taken from Luis Rodriguez's wiki -
http://kernelnewbies.org/KernelProjects/common-kernel-loader

Mimi

Dmitry Kasatkin (2):
  ima: provide buffer hash calculation function
  ima: load policy using path

Kees Cook (1):
  firmware: clean up filesystem load exit path

Luis R. Rodriguez (2):
  firmware: simplify dev_*() print messages for generic helpers
  firmware: move completing fw into a helper

Mimi Zohar (14):
  vfs: define a generic function to read a file from the kernel
  vfs: define kernel_read_file_id enumeration
  ima: calculate the hash of a buffer using aynchronous hash(ahash)
  ima: define a new hook to measure and appraise a file already in
memory
  vfs: define kernel_read_file_from_path
  firmware: replace call to fw_read_file_contents() with kernel version
  security: define kernel_read_file hook
  vfs: define kernel_copy_file_from_fd()
  module: replace copy_module_from_fd with kernel version
  ima: remove firmware and module specific cached status info
  kexec: replace call to copy_file_from_fd() with kernel version
  ima: support for kexec image and initramfs
  ima: measure and appraise the IMA policy itself
  ima: require signed IMA policy

 Documentation/ABI/testing/ima_policy  |   1 +
 drivers/base/firmware_class.c |  74 +++--
 fs/exec.c |  95 +++
 include/linux/fs.h|  15 +
 include/linux/ima.h   |  10 +--
 include/linux/lsm_hooks.h |  35 +-
 include/linux/security.h  |  16 +++--
 kernel/kexec_file.c   |  73 +++--
 kernel/module.c   |  68 +++-
 security/integrity/iint.c |   4 +-
 security/integrity/ima/ima.h  |  13 +++-
 security/integrity/ima/ima_api.c  |   6 +-
 security/integrity/ima/ima_appraise.c |  37 +--
 security/integrity/ima/ima_crypto.c   | 118 ++
 security/integrity/ima/ima_fs.c   |  51 ++-
 security/integrity/ima/ima_main.c |  73 -
 security/integrity/ima/ima_policy.c   |  41 ++--
 security/integrity/integrity.h|  15 ++---
 security/security.c   |  32 -
 19 files changed, 499 insertions(+), 278 deletions(-)

-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 06/19] ima: provide buffer hash calculation function

2016-02-12 Thread Mimi Zohar
From: Dmitry Kasatkin <d.kasat...@samsung.com>

This patch provides convenient buffer hash calculation function.

Changelog v3:
- fix while hash calculation - Dmitry
v1:
- rewrite to support loff_t sized buffers - Mimi
  (based on Fenguang Wu's testing)

Signed-off-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h|  2 ++
 security/integrity/ima/ima_crypto.c | 47 +
 2 files changed, 49 insertions(+)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index b7e7935..2c5262f 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -107,6 +107,8 @@ int ima_add_template_entry(struct ima_template_entry 
*entry, int violation,
   const char *op, struct inode *inode,
   const unsigned char *filename);
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash);
 int ima_calc_field_array_hash(struct ima_field_data *field_data,
  struct ima_template_desc *desc, int num_fields,
  struct ima_digest_data *hash);
diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index fb30ce4..fccb6ce 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -519,6 +519,53 @@ int ima_calc_field_array_hash(struct ima_field_data 
*field_data,
return rc;
 }
 
+static int calc_buffer_shash_tfm(const void *buf, loff_t size,
+   struct ima_digest_data *hash,
+   struct crypto_shash *tfm)
+{
+   SHASH_DESC_ON_STACK(shash, tfm);
+   unsigned int len;
+   int rc;
+
+   shash->tfm = tfm;
+   shash->flags = 0;
+
+   hash->length = crypto_shash_digestsize(tfm);
+
+   rc = crypto_shash_init(shash);
+   if (rc != 0)
+   return rc;
+
+   while (size) {
+   len = size < PAGE_SIZE ? size : PAGE_SIZE;
+   rc = crypto_shash_update(shash, buf, len);
+   if (rc)
+   break;
+   buf += len;
+   size -= len;
+   }
+
+   if (!rc)
+   rc = crypto_shash_final(shash, hash->digest);
+   return rc;
+}
+
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   struct crypto_shash *tfm;
+   int rc;
+
+   tfm = ima_alloc_tfm(hash->algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   rc = calc_buffer_shash_tfm(buf, len, hash, tfm);
+
+   ima_free_tfm(tfm);
+   return rc;
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
if (!ima_used_chip)
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 07/19] ima: calculate the hash of a buffer using aynchronous hash(ahash)

2016-02-12 Thread Mimi Zohar
Setting up ahash has some overhead.  Only use ahash to calculate the
hash of a buffer, if the buffer is larger than ima_ahash_minsize.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
---
 security/integrity/ima/ima_crypto.c | 75 -
 1 file changed, 73 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index fccb6ce..38f2ed8 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -519,6 +519,63 @@ int ima_calc_field_array_hash(struct ima_field_data 
*field_data,
return rc;
 }
 
+static int calc_buffer_ahash_atfm(const void *buf, loff_t len,
+ struct ima_digest_data *hash,
+ struct crypto_ahash *tfm)
+{
+   struct ahash_request *req;
+   struct scatterlist sg;
+   struct ahash_completion res;
+   int rc, ahash_rc = 0;
+
+   hash->length = crypto_ahash_digestsize(tfm);
+
+   req = ahash_request_alloc(tfm, GFP_KERNEL);
+   if (!req)
+   return -ENOMEM;
+
+   init_completion();
+   ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+  CRYPTO_TFM_REQ_MAY_SLEEP,
+  ahash_complete, );
+
+   rc = ahash_wait(crypto_ahash_init(req), );
+   if (rc)
+   goto out;
+
+   sg_init_one(, buf, len);
+   ahash_request_set_crypt(req, , NULL, len);
+
+   ahash_rc = crypto_ahash_update(req);
+
+   /* wait for the update request to complete */
+   rc = ahash_wait(ahash_rc, );
+   if (!rc) {
+   ahash_request_set_crypt(req, NULL, hash->digest, 0);
+   rc = ahash_wait(crypto_ahash_final(req), );
+   }
+out:
+   ahash_request_free(req);
+   return rc;
+}
+
+static int calc_buffer_ahash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   struct crypto_ahash *tfm;
+   int rc;
+
+   tfm = ima_alloc_atfm(hash->algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   rc = calc_buffer_ahash_atfm(buf, len, hash, tfm);
+
+   ima_free_atfm(tfm);
+
+   return rc;
+}
+
 static int calc_buffer_shash_tfm(const void *buf, loff_t size,
struct ima_digest_data *hash,
struct crypto_shash *tfm)
@@ -550,8 +607,8 @@ static int calc_buffer_shash_tfm(const void *buf, loff_t 
size,
return rc;
 }
 
-int ima_calc_buffer_hash(const void *buf, loff_t len,
-struct ima_digest_data *hash)
+static int calc_buffer_shash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
 {
struct crypto_shash *tfm;
int rc;
@@ -566,6 +623,20 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,
return rc;
 }
 
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   int rc;
+
+   if (ima_ahash_minsize && len >= ima_ahash_minsize) {
+   rc = calc_buffer_ahash(buf, len, hash);
+   if (!rc)
+   return 0;
+   }
+
+   return calc_buffer_shash(buf, len, hash);
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
if (!ima_used_chip)
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 15/19] kexec: replace call to copy_file_from_fd() with kernel version

2016-02-12 Thread Mimi Zohar
Replace copy_file_from_fd() with kernel_read_file_from_fd().

Two new identifiers named READING_KEXEC_IMAGE and READING_KEXEC_INITRAMFS
are defined for measuring, appraising or auditing the kexec image and
initramfs.

Changelog v3:
- return -EBADF, not -ENOEXEC
- identifier change
- split patch, moving copy_file_from_fd() to a separate patch
- split patch, moving IMA changes to a separate patch
v0:
- use kstat file size type loff_t, not size_t
- Calculate the file hash from the in memory buffer - Dave Young

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
Cc: Eric Biederman <ebied...@xmission.com>
Acked-by: Dave Young <dyo...@redhat.com>
---
 include/linux/fs.h  |  2 ++
 kernel/kexec_file.c | 73 +++--
 2 files changed, 11 insertions(+), 64 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index fb08b66..5256725 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2579,6 +2579,8 @@ extern int do_pipe_flags(int *, int);
 enum kernel_read_file_id {
READING_FIRMWARE = 1,
READING_MODULE,
+   READING_KEXEC_IMAGE,
+   READING_KEXEC_INITRAMFS,
READING_MAX_ID
 };
 
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 007b791..b696c3f 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,65 +34,6 @@ size_t __weak kexec_purgatory_size = 0;
 
 static int kexec_calculate_store_digests(struct kimage *image);
 
-static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len)
-{
-   struct fd f = fdget(fd);
-   int ret;
-   struct kstat stat;
-   loff_t pos;
-   ssize_t bytes = 0;
-
-   if (!f.file)
-   return -EBADF;
-
-   ret = vfs_getattr(>f_path, );
-   if (ret)
-   goto out;
-
-   if (stat.size > INT_MAX) {
-   ret = -EFBIG;
-   goto out;
-   }
-
-   /* Don't hand 0 to vmalloc, it whines. */
-   if (stat.size == 0) {
-   ret = -EINVAL;
-   goto out;
-   }
-
-   *buf = vmalloc(stat.size);
-   if (!*buf) {
-   ret = -ENOMEM;
-   goto out;
-   }
-
-   pos = 0;
-   while (pos < stat.size) {
-   bytes = kernel_read(f.file, pos, (char *)(*buf) + pos,
-   stat.size - pos);
-   if (bytes < 0) {
-   vfree(*buf);
-   ret = bytes;
-   goto out;
-   }
-
-   if (bytes == 0)
-   break;
-   pos += bytes;
-   }
-
-   if (pos != stat.size) {
-   ret = -EBADF;
-   vfree(*buf);
-   goto out;
-   }
-
-   *buf_len = pos;
-out:
-   fdput(f);
-   return ret;
-}
-
 /* Architectures can provide this probe function */
 int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
 unsigned long buf_len)
@@ -182,16 +124,17 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
 {
int ret = 0;
void *ldata;
+   loff_t size;
 
-   ret = copy_file_from_fd(kernel_fd, >kernel_buf,
-   >kernel_buf_len);
+   ret = kernel_read_file_from_fd(kernel_fd, >kernel_buf,
+  , INT_MAX, READING_KEXEC_IMAGE);
if (ret)
return ret;
+   image->kernel_buf_len = size;
 
/* Call arch image probe handlers */
ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
image->kernel_buf_len);
-
if (ret)
goto out;
 
@@ -206,10 +149,12 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
 #endif
/* It is possible that there no initramfs is being loaded */
if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
-   ret = copy_file_from_fd(initrd_fd, >initrd_buf,
-   >initrd_buf_len);
+   ret = kernel_read_file_from_fd(initrd_fd, >initrd_buf,
+  , INT_MAX,
+  READING_KEXEC_INITRAMFS);
if (ret)
goto out;
+   image->initrd_buf_len = size;
}
 
if (cmdline_len) {
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 04/19] vfs: define a generic function to read a file from the kernel

2016-02-12 Thread Mimi Zohar
For a while it was looked down upon to directly read files from Linux.
These days there exists a few mechanisms in the kernel that do just
this though to load a file into a local buffer.  There are minor but
important checks differences on each.  This patch set is the first
attempt at resolving some of these differences.

This patch introduces a common function for reading files from the kernel
with the corresponding security post-read hook and function.

Changelog v3:
- additional bounds checking - Luis
v2:
- To simplify patch review, re-ordered patches

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Reviewed-by: Luis R. Rodriguez <mcg...@suse.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Cc: Al Viro <v...@zeniv.linux.org.uk>
---
 fs/exec.c | 53 +++
 include/linux/fs.h|  1 +
 include/linux/lsm_hooks.h |  9 
 include/linux/security.h  |  7 +++
 security/security.c   |  7 +++
 5 files changed, 77 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index dcd4ac7..6b6668b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -56,6 +56,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -831,6 +832,58 @@ int kernel_read(struct file *file, loff_t offset,
 
 EXPORT_SYMBOL(kernel_read);
 
+int kernel_read_file(struct file *file, void **buf, loff_t *size,
+loff_t max_size)
+{
+   loff_t i_size, pos;
+   ssize_t bytes = 0;
+   int ret;
+
+   if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
+   return -EINVAL;
+
+   i_size = i_size_read(file_inode(file));
+   if (max_size > 0 && i_size > max_size)
+   return -EFBIG;
+   if (i_size <= 0)
+   return -EINVAL;
+
+   *buf = vmalloc(i_size);
+   if (!*buf)
+   return -ENOMEM;
+
+   pos = 0;
+   while (pos < i_size) {
+   bytes = kernel_read(file, pos, (char *)(*buf) + pos,
+   i_size - pos);
+   if (bytes < 0) {
+   ret = bytes;
+   goto out;
+   }
+
+   if (bytes == 0)
+   break;
+   pos += bytes;
+   }
+
+   if (pos != i_size) {
+   ret = -EIO;
+   goto out;
+   }
+
+   ret = security_kernel_post_read_file(file, *buf, i_size);
+   if (!ret)
+   *size = pos;
+
+out:
+   if (ret < 0) {
+   vfree(*buf);
+   *buf = NULL;
+   }
+   return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file);
+
 ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t 
len)
 {
ssize_t res = vfs_read(file, (void __user *)addr, len, );
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ae68100..9a83d82 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2577,6 +2577,7 @@ static inline void i_readcount_inc(struct inode *inode)
 extern int do_pipe_flags(int *, int);
 
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
+extern int kernel_read_file(struct file *, void **, loff_t *, loff_t);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 71969de..f82631c 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -561,6 +561,13 @@
  * the kernel module to load. If the module is being loaded from a blob,
  * this argument will be NULL.
  * Return 0 if permission is granted.
+ * @kernel_post_read_file:
+ * Read a file specified by userspace.
+ * @file contains the file structure pointing to the file being read
+ * by the kernel.
+ * @buf pointer to buffer containing the file contents.
+ * @size length of the file contents.
+ * Return 0 if permission is granted.
  * @task_fix_setuid:
  * Update the module's state after setting one or more of the user
  * identity attributes of the current process.  The @flags parameter
@@ -1457,6 +1464,7 @@ union security_list_options {
int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file);
+   int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size);
int (*task_fix_setuid)(struct cred *new, const struct cred *old,
int flags);
int (*task_setpgid)(struct task_struct *p, pid_t pgid);
@@ -1716,6 +1724,7 @@ struct security_hook_heads {
struct list_head kernel_act_as;
struct list_head kernel_create_files_as;
struct list_head kernel_fw_from_file;
+   struct list_head kernel_post_r

[PATCH v4 08/19] ima: define a new hook to measure and appraise a file already in memory

2016-02-12 Thread Mimi Zohar
This patch defines a new IMA hook ima_post_read_file() for measuring
and appraising files read by the kernel. The caller loads the file into
memory before calling this function, which calculates the hash followed by
the normal IMA policy based processing.

Changelog v3:
- rename ima_hash_and_process_file() to ima_post_read_file()

v1:
- split patch

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
---
 include/linux/ima.h   |  8 +++
 include/linux/security.h  |  1 +
 security/integrity/ima/ima.h  |  4 +++-
 security/integrity/ima/ima_api.c  |  6 +++--
 security/integrity/ima/ima_appraise.c |  2 +-
 security/integrity/ima/ima_main.c | 45 ---
 security/integrity/ima/ima_policy.c   |  1 +
 security/integrity/integrity.h|  7 --
 security/security.c   |  7 +-
 9 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 120ccc5..d29a6a2 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -20,6 +20,8 @@ extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern int ima_module_check(struct file *file);
 extern int ima_fw_from_file(struct file *file, char *buf, size_t size);
+extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
+ enum kernel_read_file_id id);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -52,6 +54,12 @@ static inline int ima_fw_from_file(struct file *file, char 
*buf, size_t size)
return 0;
 }
 
+static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
+enum kernel_read_file_id id)
+{
+   return 0;
+}
+
 #endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/include/linux/security.h b/include/linux/security.h
index b68ce94..d920718 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -24,6 +24,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 2c5262f..0b7134c 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -19,6 +19,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -152,7 +153,8 @@ enum ima_hooks {
 int ima_get_action(struct inode *inode, int mask, enum ima_hooks func);
 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file, enum hash_algo algo);
+   struct file *file, void *buf, loff_t size,
+   enum hash_algo algo);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file 
*file,
   const unsigned char *filename,
   struct evm_ima_xattr_data *xattr_value,
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 8750254..370e42d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -188,7 +188,8 @@ int ima_get_action(struct inode *inode, int mask, enum 
ima_hooks func)
  * Return 0 on success, error code otherwise
  */
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file, enum hash_algo algo)
+   struct file *file, void *buf, loff_t size,
+   enum hash_algo algo)
 {
const char *audit_cause = "failed";
struct inode *inode = file_inode(file);
@@ -210,7 +211,8 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
 
hash.hdr.algo = algo;
 
-   result = ima_calc_file_hash(file, );
+   result = (!buf) ?  ima_calc_file_hash(file, ) :
+   ima_calc_buffer_hash(buf, size, );
if (!result) {
int length = sizeof(hash.hdr) + hash.hdr.length;
void *tmpbuf = krealloc(iint->ima_hash, length,
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 2888449..cb0d0ff 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -300,7 +300,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, 
struct file *file)
if (iint->flags & IMA_DIGSIG)
return;
 
-   rc = ima_collect_measurement(iint, file, ima_hash_algo);
+   rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo);
if (rc < 0)
return;
 
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index 1be99a2..cfb508b 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security

[PATCH v4 16/19] ima: support for kexec image and initramfs

2016-02-12 Thread Mimi Zohar
Add IMA policy support for measuring/appraising the kexec image and
initramfs. Two new IMA policy identifiers KEXEC_KERNEL_CHECK and
KEXEC_INITRAMFS_CHECK are defined.

Example policy rules:
measure func=KEXEC_KERNEL_CHECK
appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig
measure func=KEXEC_INITRAMFS_CHECK
appraise func=KEXEC_INITRAMFS_CHECK appraise_type=imasig

Moving the enumeration to the vfs layer simplified the patches, allowing
the IMA changes, for the most part, to be separated from the other
changes.  Unfortunately, passing either a kernel_read_file_id or a
ima_hooks enumeration within IMA is messy.

Option 1: duplicate kernel_read_file enumeration in ima_hooks

enum kernel_read_file_id {
...
READING_KEXEC_IMAGE,
READING_KEXEC_INITRAMFS,
READING_MAX_ID

enum ima_hooks {
...
KEXEC_KERNEL_CHECK
KEXEC_INITRAMFS_CHECK

Option 2: define ima_hooks as extension of kernel_read_file
eg: enum ima_hooks {
FILE_CHECK = READING_MAX_ID,
MMAP_CHECK,

In order to pass both kernel_read_file_id and ima_hooks values, we
would need to specify a struct containing a union.

struct caller_id {
union {
enum ima_hooks func_id;
enum kernel_read_file_id read_id;
};
};

Option 3: incorportate the ima_hooks enumeration into kernel_read_file_id,
perhaps changing the enumeration name.

For now, duplicate the new READING_KEXEC_IMAGE/INITRAMFS in the ima_hooks.

Changelog v4:
- replaced switch statement with a kernel_read_file_id to an ima_hooks
id mapping array - Dmitry
- renamed ima_hook tokens KEXEC_CHECK and INITRAMFS_CHECK to
KEXEC_KERNEL_CHECK and KEXEC_INITRAMFS_CHECK respectively - Dave Young

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Petko Manolov <pet...@mip-labs.com>
Acked-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
Cc: Dave Young <dyo...@redhat.com>
---
 Documentation/ABI/testing/ima_policy |  1 +
 security/integrity/ima/ima.h |  2 ++
 security/integrity/ima/ima_main.c| 15 +--
 security/integrity/ima/ima_policy.c  | 15 ++-
 4 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 0a378a8..bb0f9a1 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -27,6 +27,7 @@ Description:
 
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
[FIRMWARE_CHECK]
+   [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
   [[^]MAY_EXEC]
fsmagic:= hex value
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index a5d2592..bd97e0d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -147,6 +147,8 @@ enum ima_hooks {
POST_SETATTR,
MODULE_CHECK,
FIRMWARE_CHECK,
+   KEXEC_KERNEL_CHECK,
+   KEXEC_INITRAMFS_CHECK,
MAX_CHECK
 };
 
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index f6039f5..4d0bdf1 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -339,6 +339,13 @@ int ima_read_file(struct file *file, enum 
kernel_read_file_id read_id)
return 0;
 }
 
+static int read_idmap[READING_MAX_ID] = {
+   [READING_FIRMWARE] = FIRMWARE_CHECK,
+   [READING_MODULE] = MODULE_CHECK,
+   [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
+   [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
+};
+
 /**
  * ima_post_read_file - in memory collect/appraise/audit measurement
  * @file: pointer to the file to be measured/appraised/audit
@@ -355,7 +362,7 @@ int ima_read_file(struct file *file, enum 
kernel_read_file_id read_id)
 int ima_post_read_file(struct file *file, void *buf, loff_t size,
   enum kernel_read_file_id read_id)
 {
-   enum ima_hooks func = FILE_CHECK;
+   enum ima_hooks func;
 
if (!file && read_id == READING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
@@ -373,11 +380,7 @@ int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
return 0;
}
 
-   if (read_id == READING_FIRMWARE)
-   func = FIRMWARE_CHECK;
-   else if (read_id == READING_MODULE)
-   func = MODULE_CHECK;
-
+   func = read_idmap[read_id] ?: FILE_CHECK;
return process_measurement(file, buf, size, MAY_READ, func, 0);
 }
 
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 7571ce8..5ccd3f5 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -612,6 +612,12 @@ static int ima_parse_ru

[PATCH v4 12/19] vfs: define kernel_copy_file_from_fd()

2016-02-12 Thread Mimi Zohar
This patch defines kernel_read_file_from_fd(), a wrapper for the VFS
common kernel_read_file().

Changelog:
- Separated from the kernel modules patch
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
Cc: Al Viro <v...@zeniv.linux.org.uk>

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 fs/exec.c  | 16 
 include/linux/fs.h |  2 ++
 2 files changed, 18 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index 78dfdf3..604f669 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -910,6 +910,22 @@ int kernel_read_file_from_path(char *path, void **buf, 
loff_t *size,
 }
 EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
 
+int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
+enum kernel_read_file_id id)
+{
+   struct fd f = fdget(fd);
+   int ret = -EBADF;
+
+   if (!f.file)
+   goto out;
+
+   ret = kernel_read_file(f.file, buf, size, max_size, id);
+out:
+   fdput(f);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
+
 ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t 
len)
 {
ssize_t res = vfs_read(file, (void __user *)addr, len, );
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c8bc4d8..9c85dea 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2586,6 +2586,8 @@ extern int kernel_read_file(struct file *, void **, 
loff_t *, loff_t,
enum kernel_read_file_id);
 extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
  enum kernel_read_file_id);
+extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
+   enum kernel_read_file_id);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 09/19] vfs: define kernel_read_file_from_path

2016-02-12 Thread Mimi Zohar
This patch defines kernel_read_file_from_path(), a wrapper for the VFS
common kernel_read_file().

Changelog:
- Separated from the IMA patch

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
Cc: Al Viro <v...@zeniv.linux.org.uk>
---
 fs/exec.c  | 22 ++
 include/linux/fs.h |  2 ++
 2 files changed, 24 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index 1138dc5..67816a0 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -884,6 +884,28 @@ out:
 }
 EXPORT_SYMBOL_GPL(kernel_read_file);
 
+int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
+  loff_t max_size, enum kernel_read_file_id id)
+{
+   struct file *file;
+   int ret;
+
+   if (!path || !*path)
+   return -EINVAL;
+
+   file = filp_open(path, O_RDONLY, 0);
+   if (IS_ERR(file)) {
+   ret = PTR_ERR(file);
+   pr_err("Unable to open file: %s (%d)", path, ret);
+   return ret;
+   }
+
+   ret = kernel_read_file(file, buf, size, max_size, id);
+   fput(file);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
+
 ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t 
len)
 {
ssize_t res = vfs_read(file, (void __user *)addr, len, );
diff --git a/include/linux/fs.h b/include/linux/fs.h
index aa84bcb..00fa5c4 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2583,6 +2583,8 @@ enum kernel_read_file_id {
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
 extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
enum kernel_read_file_id);
+extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
+ enum kernel_read_file_id);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 13/19] module: replace copy_module_from_fd with kernel version

2016-02-12 Thread Mimi Zohar
Replace copy_module_from_fd() with kernel_read_file_from_fd().

Although none of the upstreamed LSMs define a kernel_module_from_file
hook, IMA is called, based on policy, to prevent unsigned kernel modules
from being loaded by the original kernel module syscall and to
measure/appraise signed kernel modules.

The security function security_kernel_module_from_file() was called prior
to reading a kernel module.  Preventing unsigned kernel modules from being
loaded by the original kernel module syscall remains on the pre-read
kernel_read_file() security hook.  Instead of reading the kernel module
twice, once for measuring/appraising and again for loading the kernel
module, the signature validation is moved to the kernel_post_read_file()
security hook.

This patch removes the security_kernel_module_from_file() hook and security
call.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
Cc: Rusty Russell <ru...@rustcorp.com.au>
---
 include/linux/fs.h|  1 +
 include/linux/ima.h   |  6 
 include/linux/lsm_hooks.h |  7 
 include/linux/security.h  |  5 ---
 kernel/module.c   | 68 +--
 security/integrity/ima/ima_main.c | 35 
 security/security.c   | 12 ---
 7 files changed, 22 insertions(+), 112 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9c85dea..fb08b66 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2578,6 +2578,7 @@ extern int do_pipe_flags(int *, int);
 
 enum kernel_read_file_id {
READING_FIRMWARE = 1,
+   READING_MODULE,
READING_MAX_ID
 };
 
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 6adcaea..e6516cb 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -18,7 +18,6 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask, int opened);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
-extern int ima_module_check(struct file *file);
 extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
 extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
  enum kernel_read_file_id id);
@@ -44,11 +43,6 @@ static inline int ima_file_mmap(struct file *file, unsigned 
long prot)
return 0;
 }
 
-static inline int ima_module_check(struct file *file)
-{
-   return 0;
-}
-
 static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
 {
return 0;
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index d32b7bd..cdee11c 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -546,12 +546,6 @@
  * userspace to load a kernel module with the given name.
  * @kmod_name name of the module requested by the kernel
  * Return 0 if successful.
- * @kernel_module_from_file:
- * Load a kernel module from userspace.
- * @file contains the file structure pointing to the file containing
- * the kernel module to load. If the module is being loaded from a blob,
- * this argument will be NULL.
- * Return 0 if permission is granted.
  * @kernel_read_file:
  * Read a file specified by userspace.
  * @file contains the file structure pointing to the file being read
@@ -1725,7 +1719,6 @@ struct security_hook_heads {
struct list_head kernel_read_file;
struct list_head kernel_post_read_file;
struct list_head kernel_module_request;
-   struct list_head kernel_module_from_file;
struct list_head task_fix_setuid;
struct list_head task_setpgid;
struct list_head task_getpgid;
diff --git a/include/linux/security.h b/include/linux/security.h
index 071fb74..157f0cb 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -859,11 +859,6 @@ static inline int security_kernel_module_request(char 
*kmod_name)
return 0;
 }
 
-static inline int security_kernel_module_from_file(struct file *file)
-{
-   return 0;
-}
-
 static inline int security_kernel_read_file(struct file *file,
enum kernel_read_file_id id)
 {
diff --git a/kernel/module.c b/kernel/module.c
index 8358f46..9554109 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2654,7 +2654,7 @@ static int copy_module_from_user(const void __user *umod, 
unsigned long len,
if (info->len < sizeof(*(info->hdr)))
return -ENOEXEC;
 
-   err = security_kernel_module_from_file(NULL);
+   err = security_kernel_read_file(NULL, READING_MODULE);
if (err)
return err;
 
@@ -2672,63 +2672,6 @@ static int copy_module_from_user(const void __user 
*umod, unsigned long len,
return 0;
 }
 
-/* Sets info-&

[PATCH v4 11/19] security: define kernel_read_file hook

2016-02-12 Thread Mimi Zohar
The kernel_read_file security hook is called prior to reading the file
into memory.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
Acked-by: Casey Schaufler <ca...@schaufler-ca.com>
---
 fs/exec.c |  4 
 include/linux/ima.h   |  6 ++
 include/linux/lsm_hooks.h |  8 
 include/linux/security.h  |  7 +++
 security/integrity/ima/ima_main.c | 16 
 security/security.c   | 12 
 6 files changed, 53 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index 67816a0..78dfdf3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -842,6 +842,10 @@ int kernel_read_file(struct file *file, void **buf, loff_t 
*size,
if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
return -EINVAL;
 
+   ret = security_kernel_read_file(file, id);
+   if (ret)
+   return ret;
+
i_size = i_size_read(file_inode(file));
if (max_size > 0 && i_size > max_size)
return -EFBIG;
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 7aea486..6adcaea 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -19,6 +19,7 @@ extern int ima_file_check(struct file *file, int mask, int 
opened);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern int ima_module_check(struct file *file);
+extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
 extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
  enum kernel_read_file_id id);
 
@@ -48,6 +49,11 @@ static inline int ima_module_check(struct file *file)
return 0;
 }
 
+static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
+{
+   return 0;
+}
+
 static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
 enum kernel_read_file_id id)
 {
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 7d04a12..d32b7bd 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -552,6 +552,12 @@
  * the kernel module to load. If the module is being loaded from a blob,
  * this argument will be NULL.
  * Return 0 if permission is granted.
+ * @kernel_read_file:
+ * Read a file specified by userspace.
+ * @file contains the file structure pointing to the file being read
+ * by the kernel.
+ * @id kernel read file identifier
+ * Return 0 if permission is granted.
  * @kernel_post_read_file:
  * Read a file specified by userspace.
  * @file contains the file structure pointing to the file being read
@@ -1455,6 +1461,7 @@ union security_list_options {
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file);
+   int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id);
int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
 enum kernel_read_file_id id);
int (*task_fix_setuid)(struct cred *new, const struct cred *old,
@@ -1715,6 +1722,7 @@ struct security_hook_heads {
struct list_head cred_transfer;
struct list_head kernel_act_as;
struct list_head kernel_create_files_as;
+   struct list_head kernel_read_file;
struct list_head kernel_post_read_file;
struct list_head kernel_module_request;
struct list_head kernel_module_from_file;
diff --git a/include/linux/security.h b/include/linux/security.h
index cee1349..071fb74 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -302,6 +302,7 @@ int security_kernel_act_as(struct cred *new, u32 secid);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
 int security_kernel_module_request(char *kmod_name);
 int security_kernel_module_from_file(struct file *file);
+int security_kernel_read_file(struct file *file, enum kernel_read_file_id id);
 int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
   enum kernel_read_file_id id);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
@@ -863,6 +864,12 @@ static inline int security_kernel_module_from_file(struct 
file *file)
return 0;
 }
 
+static inline int security_kernel_read_file(struct file *file,
+   enum kernel_read_file_id id)
+{
+   return 0;
+}
+
 static inline int security_kernel_post_read_file(struct file *file,
 char *buf, loff_t size,
 enum kernel_read_file_id id)
diff --git a/s

[PATCH v4 14/19] ima: remove firmware and module specific cached status info

2016-02-12 Thread Mimi Zohar
Each time a file is read by the kernel, the file should be re-measured and
the file signature re-appraised, based on policy.  As there is no need to
preserve the status information, this patch replaces the firmware and
module specific cache status with a generic one named read_file.

This change simplifies adding support for other files read by the kernel.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Petko Manolov <pet...@mip-labs.com>
Acked-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
---
 security/integrity/iint.c |  4 ++--
 security/integrity/ima/ima.h  |  3 ++-
 security/integrity/ima/ima_appraise.c | 35 ---
 security/integrity/ima/ima_policy.c   |  9 -
 security/integrity/integrity.h| 16 
 5 files changed, 28 insertions(+), 39 deletions(-)

diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 8f1ab37..345b759 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -77,7 +77,7 @@ static void iint_free(struct integrity_iint_cache *iint)
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
-   iint->ima_module_status = INTEGRITY_UNKNOWN;
+   iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
kmem_cache_free(iint_cache, iint);
 }
@@ -157,7 +157,7 @@ static void init_once(void *foo)
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
-   iint->ima_module_status = INTEGRITY_UNKNOWN;
+   iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
 }
 
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 0b7134c..a5d2592 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -144,9 +144,10 @@ enum ima_hooks {
FILE_CHECK = 1,
MMAP_CHECK,
BPRM_CHECK,
+   POST_SETATTR,
MODULE_CHECK,
FIRMWARE_CHECK,
-   POST_SETATTR
+   MAX_CHECK
 };
 
 /* LIM API function definitions */
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index cb0d0ff..6b4694a 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -74,13 +74,12 @@ enum integrity_status ima_get_cache_status(struct 
integrity_iint_cache *iint,
return iint->ima_mmap_status;
case BPRM_CHECK:
return iint->ima_bprm_status;
-   case MODULE_CHECK:
-   return iint->ima_module_status;
-   case FIRMWARE_CHECK:
-   return iint->ima_firmware_status;
case FILE_CHECK:
-   default:
+   case POST_SETATTR:
return iint->ima_file_status;
+   case MODULE_CHECK ... MAX_CHECK - 1:
+   default:
+   return iint->ima_read_status;
}
 }
 
@@ -95,15 +94,14 @@ static void ima_set_cache_status(struct 
integrity_iint_cache *iint,
case BPRM_CHECK:
iint->ima_bprm_status = status;
break;
-   case MODULE_CHECK:
-   iint->ima_module_status = status;
-   break;
-   case FIRMWARE_CHECK:
-   iint->ima_firmware_status = status;
-   break;
case FILE_CHECK:
-   default:
+   case POST_SETATTR:
iint->ima_file_status = status;
+   break;
+   case MODULE_CHECK ... MAX_CHECK - 1:
+   default:
+   iint->ima_read_status = status;
+   break;
}
 }
 
@@ -117,15 +115,14 @@ static void ima_cache_flags(struct integrity_iint_cache 
*iint,
case BPRM_CHECK:
iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED);
break;
-   case MODULE_CHECK:
-   iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED);
-   break;
-   case FIRMWARE_CHECK:
-   iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED);
-   break;
case FILE_CHECK:
-   default:
+   case POST_SETATTR:
iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED);
+   break;
+   case MODULE_CHECK ... MAX_CHECK - 1:
+   default:
+   iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED);
+   break;
}
 }
 
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index cfbe86f..7571ce8 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -300,13 +300,12 @@ static int get_subaction(struct ima_rule_entry *rule, 
enum ima_hooks func)
return IMA_MMAP_APPRAISE;
case BPRM_CHECK:
 

[PATCH v4 17/19] ima: load policy using path

2016-02-12 Thread Mimi Zohar
From: Dmitry Kasatkin <d.kasat...@samsung.com>

We currently cannot do appraisal or signature vetting of IMA policies
since we currently can only load IMA policies by writing the contents
of the policy directly in, as follows:

cat policy-file > /ima/policy

If we provide the kernel the path to the IMA policy so it can load
the policy itself it'd be able to later appraise or vet the file
signature if it has one.  This patch adds support to load the IMA
policy with a given path as follows:

echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy

Changelog v3:
- moved kernel_read_file_from_path() to a separate patch
v2:
- after re-ordering the patches, replace calling integrity_kernel_read()
  to read the file with kernel_read_file_from_path() (Mimi)
- Patch description re-written by Luis R. Rodriguez

Signed-off-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/fs.h  |  1 +
 security/integrity/ima/ima_fs.c | 43 +++--
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5256725..e514f76 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2581,6 +2581,7 @@ enum kernel_read_file_id {
READING_MODULE,
READING_KEXEC_IMAGE,
READING_KEXEC_INITRAMFS,
+   READING_POLICY,
READING_MAX_ID
 };
 
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index f355231..57989a4 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ima.h"
 
@@ -258,6 +259,41 @@ static const struct file_operations 
ima_ascii_measurements_ops = {
.release = seq_release,
 };
 
+static ssize_t ima_read_policy(char *path)
+{
+   void *data;
+   char *datap;
+   loff_t size;
+   int rc, pathlen = strlen(path);
+
+   char *p;
+
+   /* remove \n */
+   datap = path;
+   strsep(, "\n");
+
+   rc = kernel_read_file_from_path(path, , , 0, READING_POLICY);
+   if (rc < 0)
+   return rc;
+
+   datap = data;
+   while (size > 0 && (p = strsep(, "\n"))) {
+   pr_debug("rule: %s\n", p);
+   rc = ima_parse_add_rule(p);
+   if (rc < 0)
+   break;
+   size -= rc;
+   }
+
+   vfree(data);
+   if (rc < 0)
+   return rc;
+   else if (size)
+   return -EINVAL;
+   else
+   return pathlen;
+}
+
 static ssize_t ima_write_policy(struct file *file, const char __user *buf,
size_t datalen, loff_t *ppos)
 {
@@ -286,9 +322,12 @@ static ssize_t ima_write_policy(struct file *file, const 
char __user *buf,
result = mutex_lock_interruptible(_write_mutex);
if (result < 0)
goto out_free;
-   result = ima_parse_add_rule(data);
-   mutex_unlock(_write_mutex);
 
+   if (data[0] == '/')
+   result = ima_read_policy(data);
+   else 
+   result = ima_parse_add_rule(data);
+   mutex_unlock(_write_mutex);
 out_free:
kfree(data);
 out:
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 19/19] ima: require signed IMA policy

2016-02-12 Thread Mimi Zohar
Require the IMA policy to be signed when additional rules can be added.

v1:
- initialize the policy flag
- include IMA_APPRAISE_POLICY in the policy flag

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Petko Manolov <pet...@mip-labs.com>
Acked-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
---
 security/integrity/ima/ima_policy.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 77a9fee..864f73d 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -129,6 +129,10 @@ static struct ima_rule_entry default_appraise_rules[] = {
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = 
IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = 
IMA_FSMAGIC},
+#ifdef CONFIG_IMA_WRITE_POLICY
+   {.action = APPRAISE, .func = POLICY_CHECK,
+   .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
 #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
 #else
@@ -412,9 +416,12 @@ void __init ima_init_policy(void)
for (i = 0; i < appraise_entries; i++) {
list_add_tail(_appraise_rules[i].list,
  _default_rules);
+   if (default_appraise_rules[i].func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
}
 
ima_rules = _default_rules;
+   ima_update_policy_flag();
 }
 
 /* Make sure we have a valid policy, at least containing some rules. */
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 10/19] firmware: replace call to fw_read_file_contents() with kernel version

2016-02-12 Thread Mimi Zohar
Replace the fw_read_file_contents with kernel_file_read_from_path().

Although none of the upstreamed LSMs define a kernel_fw_from_file hook,
IMA is called by the security function to prevent unsigned firmware from
being loaded and to measure/appraise signed firmware, based on policy.

Instead of reading the firmware twice, once for measuring/appraising the
firmware and again for reading the firmware contents into memory, the
kernel_post_read_file() security hook calculates the file hash based on
the in memory file buffer.  The firmware is read once.

This patch removes the LSM kernel_fw_from_file() hook and security call.

Changelog v3:
- remove kernel_fw_from_file hook
- use kernel_file_read_from_path() - requested by Luis
v2:
- reordered and squashed firmware patches
- fix MAX firmware size (Kees Cook)

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
---
 drivers/base/firmware_class.c | 48 +++
 include/linux/fs.h|  1 +
 include/linux/ima.h   |  6 -
 include/linux/lsm_hooks.h | 11 -
 include/linux/security.h  |  7 --
 security/integrity/ima/ima_main.c | 21 -
 security/security.c   | 13 ---
 7 files changed, 19 insertions(+), 88 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index c743a2f..dd588ea 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -291,37 +292,6 @@ static const char * const fw_path[] = {
 module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
 MODULE_PARM_DESC(path, "customized firmware image search path with a higher 
priority than default path");
 
-static int fw_read_file_contents(struct file *file, struct firmware_buf 
*fw_buf)
-{
-   int size;
-   char *buf;
-   int rc;
-
-   if (!S_ISREG(file_inode(file)->i_mode))
-   return -EINVAL;
-   size = i_size_read(file_inode(file));
-   if (size <= 0)
-   return -EINVAL;
-   buf = vmalloc(size);
-   if (!buf)
-   return -ENOMEM;
-   rc = kernel_read(file, 0, buf, size);
-   if (rc != size) {
-   if (rc > 0)
-   rc = -EIO;
-   goto fail;
-   }
-   rc = security_kernel_fw_from_file(file, buf, size);
-   if (rc)
-   goto fail;
-   fw_buf->data = buf;
-   fw_buf->size = size;
-   return 0;
-fail:
-   vfree(buf);
-   return rc;
-}
-
 static void fw_finish_direct_load(struct device *device,
  struct firmware_buf *buf)
 {
@@ -334,6 +304,7 @@ static void fw_finish_direct_load(struct device *device,
 static int fw_get_filesystem_firmware(struct device *device,
   struct firmware_buf *buf)
 {
+   loff_t size;
int i, len;
int rc = -ENOENT;
char *path;
@@ -343,8 +314,6 @@ static int fw_get_filesystem_firmware(struct device *device,
return -ENOMEM;
 
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-   struct file *file;
-
/* skip the unset customized path */
if (!fw_path[i][0])
continue;
@@ -356,11 +325,9 @@ static int fw_get_filesystem_firmware(struct device 
*device,
break;
}
 
-   file = filp_open(path, O_RDONLY, 0);
-   if (IS_ERR(file))
-   continue;
-   rc = fw_read_file_contents(file, buf);
-   fput(file);
+   buf->size = 0;
+   rc = kernel_read_file_from_path(path, >data, ,
+   INT_MAX, READING_FIRMWARE);
if (rc) {
dev_warn(device, "loading %s failed with error %d\n",
 path, rc);
@@ -689,8 +656,9 @@ static ssize_t firmware_loading_store(struct device *dev,
dev_err(dev, "%s: map pages failed\n",
__func__);
else
-   rc = security_kernel_fw_from_file(NULL,
-   fw_buf->data, fw_buf->size);
+   rc = security_kernel_post_read_file(NULL,
+   fw_buf->data, fw_buf->size,
+   READING_FIRMWARE);
 
/*
 * Same logic as fw_load_abort, only the DONE bit
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 00fa5c4..c8bc4d8 100644
--- a/include/linux/fs

[PATCH v4 02/19] firmware: move completing fw into a helper

2016-02-12 Thread Mimi Zohar
From: "Luis R. Rodriguez" <mcg...@kernel.org>

This will be re-used later through a new extensible interface.

Reviewed-by: Josh Boyer <jwbo...@fedoraproject.org>
Signed-off-by: Luis R. Rodriguez <mcg...@kernel.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
---
 drivers/base/firmware_class.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index ce88355..7bc4ad0 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -322,6 +322,15 @@ fail:
return rc;
 }
 
+static void fw_finish_direct_load(struct device *device,
+ struct firmware_buf *buf)
+{
+   mutex_lock(_lock);
+   set_bit(FW_STATUS_DONE, >status);
+   complete_all(>completion);
+   mutex_unlock(_lock);
+}
+
 static int fw_get_filesystem_firmware(struct device *device,
   struct firmware_buf *buf)
 {
@@ -363,10 +372,7 @@ static int fw_get_filesystem_firmware(struct device 
*device,
if (!rc) {
dev_dbg(device, "direct-loading %s\n",
buf->fw_id);
-   mutex_lock(_lock);
-   set_bit(FW_STATUS_DONE, >status);
-   complete_all(>completion);
-   mutex_unlock(_lock);
+   fw_finish_direct_load(device, buf);
}
 
return rc;
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 18/19] ima: measure and appraise the IMA policy itself

2016-02-12 Thread Mimi Zohar
Add support for measuring and appraising the IMA policy itself.

Changelog v4:
- use braces on both if/else branches, even if single line on one of the
branches - Dmitry
- Use the id mapping - Dmitry

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Petko Manolov <pet...@mip-labs.com>
Acked-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
---
 security/integrity/ima/ima.h|  2 ++
 security/integrity/ima/ima_fs.c | 12 ++--
 security/integrity/ima/ima_main.c   |  1 +
 security/integrity/ima/ima_policy.c | 11 ++-
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index bd97e0d..5d0f611 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -149,6 +149,7 @@ enum ima_hooks {
FIRMWARE_CHECK,
KEXEC_KERNEL_CHECK,
KEXEC_INITRAMFS_CHECK,
+   POLICY_CHECK,
MAX_CHECK
 };
 
@@ -191,6 +192,7 @@ int ima_policy_show(struct seq_file *m, void *v);
 #define IMA_APPRAISE_LOG   0x04
 #define IMA_APPRAISE_MODULES   0x08
 #define IMA_APPRAISE_FIRMWARE  0x10
+#define IMA_APPRAISE_POLICY0x20
 
 #ifdef CONFIG_IMA_APPRAISE
 int ima_appraise_measurement(enum ima_hooks func,
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 57989a4..9f8cb10 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -323,10 +323,18 @@ static ssize_t ima_write_policy(struct file *file, const 
char __user *buf,
if (result < 0)
goto out_free;
 
-   if (data[0] == '/')
+   if (data[0] == '/') {
result = ima_read_policy(data);
-   else 
+   } else if (ima_appraise & IMA_APPRAISE_POLICY) {
+   pr_err("IMA: signed policy file (specified as an absolute 
pathname) required\n");
+   integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
+   "policy_update", "signed policy required",
+   1, 0);
+   if (ima_appraise & IMA_APPRAISE_ENFORCE)
+   result = -EACCES;
+   } else {
result = ima_parse_add_rule(data);
+   }
mutex_unlock(_write_mutex);
 out_free:
kfree(data);
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index 4d0bdf1..b14c1c1 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -344,6 +344,7 @@ static int read_idmap[READING_MAX_ID] = {
[READING_MODULE] = MODULE_CHECK,
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
+   [READING_POLICY] = POLICY_CHECK
 };
 
 /**
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 5ccd3f5..77a9fee 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -114,6 +114,7 @@ static struct ima_rule_entry default_measurement_rules[] = {
 .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
+   {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_appraise_rules[] = {
@@ -618,6 +619,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
 == 0)
entry->func = KEXEC_INITRAMFS_CHECK;
+   else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
+   entry->func = POLICY_CHECK;
else
result = -EINVAL;
if (!result)
@@ -776,6 +779,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
temp_ima_appraise |= IMA_APPRAISE_MODULES;
else if (entry->func == FIRMWARE_CHECK)
temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
+   else if (entry->func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
audit_log_format(ab, "res=%d", !result);
audit_log_end(ab);
return result;
@@ -862,7 +867,8 @@ static char *mask_tokens[] = {
 enum {
func_file = 0, func_mmap, func_bprm,
func_module, func_firmware, func_post,
-   func_kexec_kernel, func_kexec_initramfs
+   func_kexec_kernel, func_kexec_initramfs,
+   func_policy
 };
 
 static char *func_tokens[] = {
@@ -942,6 +948,9 @@ static void policy_func_show(struct seq_file *m, enum 
ima_hooks func)
case KEXEC_INITRAMFS_CHECK:
seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
   

[PATCH v4 03/19] firmware: clean up filesystem load exit path

2016-02-12 Thread Mimi Zohar
From: Kees Cook <keesc...@chromium.org>

This makes the error and success paths more readable while trying to
load firmware from the filesystem.

Signed-off-by: Kees Cook <keesc...@chromium.org>
Cc: Josh Boyer <jwbo...@fedoraproject.org>
Cc: David Howells <dhowe...@redhat.com>
Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 drivers/base/firmware_class.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 7bc4ad0..c743a2f 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -361,19 +361,17 @@ static int fw_get_filesystem_firmware(struct device 
*device,
continue;
rc = fw_read_file_contents(file, buf);
fput(file);
-   if (rc)
+   if (rc) {
dev_warn(device, "loading %s failed with error %d\n",
 path, rc);
-   else
-   break;
-   }
-   __putname(path);
-
-   if (!rc) {
+   continue;
+   }
dev_dbg(device, "direct-loading %s\n",
buf->fw_id);
fw_finish_direct_load(device, buf);
+   break;
}
+   __putname(path);
 
return rc;
 }
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v4 01/19] firmware: simplify dev_*() print messages for generic helpers

2016-02-12 Thread Mimi Zohar
From: "Luis R. Rodriguez" <mcg...@kernel.org>

Simplify a few of the *generic* shared dev_warn() and dev_dbg()
print messages for three reasons:

0) Historically firmware_class code was added to help
   get device driver firmware binaries but these days
   request_firmware*() helpers are being repurposed for
   general *system data* needed by the kernel.

1) This will also help generalize shared code as much as possible
   later in the future in consideration for a new extensible firmware
   API which will enable to separate usermode helper code out as much
   as possible.

2) Kees Cook pointed out the the prints already have the device
   associated as dev_*() helpers are used, that should help identify
   the user and case in which the helpers are used. That should provide
   enough context and simplifies the messages further.

v4: generalize debug/warn messages even further as suggested by
Kees Cook.

Cc: Rusty Russell <ru...@rustcorp.com.au>
Cc: Andrew Morton <a...@linux-foundation.org>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Cc: David Howells <dhowe...@redhat.com>
Cc: Kees Cook <keesc...@chromium.org>
Cc: Casey Schaufler <ca...@schaufler-ca.com>
Cc: Ming Lei <ming@canonical.com>
Cc: Takashi Iwai <ti...@suse.de>
Cc: Vojtěch Pavlík <vojt...@suse.cz>
Cc: Kyle McMartin <k...@kernel.org>
Cc: Matthew Garrett <mj...@srcf.ucam.org>
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Luis R. Rodriguez <mcg...@kernel.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
---
 drivers/base/firmware_class.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index b9250e5..ce88355 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -353,15 +353,15 @@ static int fw_get_filesystem_firmware(struct device 
*device,
rc = fw_read_file_contents(file, buf);
fput(file);
if (rc)
-   dev_warn(device, "firmware, attempted to load %s, but 
failed with error %d\n",
-   path, rc);
+   dev_warn(device, "loading %s failed with error %d\n",
+path, rc);
else
break;
}
__putname(path);
 
if (!rc) {
-   dev_dbg(device, "firmware: direct-loading firmware %s\n",
+   dev_dbg(device, "direct-loading %s\n",
buf->fw_id);
mutex_lock(_lock);
set_bit(FW_STATUS_DONE, >status);
@@ -1051,7 +1051,7 @@ _request_firmware_prepare(struct firmware **firmware_p, 
const char *name,
}
 
if (fw_get_builtin_firmware(firmware, name)) {
-   dev_dbg(device, "firmware: using built-in firmware %s\n", name);
+   dev_dbg(device, "using built-in %s\n", name);
return 0; /* assigned */
}
 
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 14/22] security: define kernel_read_file hook

2016-02-11 Thread Mimi Zohar
On Thu, 2016-02-11 at 08:54 -0800, Casey Schaufler wrote:
> On 2/3/2016 11:06 AM, Mimi Zohar wrote:
> > The kernel_read_file security hook is called prior to reading the file
> > into memory.
> >
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> 
> Acked-by: Casey Schaufler <ca...@schaufler-ca.com>
> 
> Being able to deny the read prior to performing any
> real work makes a lot of sense.

Thanks, Casey!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 19/22] ima: support for kexec image and initramfs

2016-02-11 Thread Mimi Zohar
On Thu, 2016-02-11 at 10:47 +0200, Dmitry Kasatkin wrote:
> On Thu, Feb 11, 2016 at 4:08 AM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:

> static int idmap[] = {
>  [READING_FIRMWARE] = FIRMWARE_CHECK,
>  [READING_MODULE] = MODULE_CHECK,
>  ...
> };

That works nicely, even with non-sequential ordering or missing entries.
The switch case be replaced with a single line:

func = read_idmap[read_id] == 0 ? FILE_CHECK : read_idmap[read_id]; 

Thank you!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 21/22] ima: measure and appraise the IMA policy itself

2016-02-10 Thread Mimi Zohar
On Wed, 2016-02-10 at 22:22 +0200, Dmitry Kasatkin wrote:
> On Wed, Feb 3, 2016 at 9:06 PM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > Add support for measuring and appraising the IMA policy itself.
> >
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> 
> Acked-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
> 
> But from Documentation/CodingStyle
> 
> if (condition)
> do_this();
> else
> do_that();
> 
> This does not apply if only one branch of a conditional statement is a single
> statement; in the latter case use braces in both branches:
> 
> if (condition) {
>  do_this();
>  do_that();
> } else {
>  otherwise();
> }
> 
> 
> You have similar issue in other patches as well...
> 
> Dmitry

Ok, I'll find and fix them.  Thank you for the review!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 17/22] ima: remove firmware and module specific cached status info

2016-02-10 Thread Mimi Zohar
On Wed, 2016-02-10 at 22:18 +0200, Dmitry Kasatkin wrote:

> > diff --git a/security/integrity/ima/ima_appraise.c 
> > b/security/integrity/ima/ima_appraise.c
> > index cb0d0ff..6b4694a 100644
> > --- a/security/integrity/ima/ima_appraise.c
> > +++ b/security/integrity/ima/ima_appraise.c
> > @@ -74,13 +74,12 @@ enum integrity_status ima_get_cache_status(struct 
> > integrity_iint_cache *iint,
> > return iint->ima_mmap_status;
> > case BPRM_CHECK:
> > return iint->ima_bprm_status;
> > -   case MODULE_CHECK:
> > -   return iint->ima_module_status;
> > -   case FIRMWARE_CHECK:
> > -   return iint->ima_firmware_status;
> > case FILE_CHECK:
> > -   default:
> > +   case POST_SETATTR:
> > return iint->ima_file_status;
> > +   case MODULE_CHECK ... MAX_CHECK - 1:
> 
> Will LLVM clang handles this range?
> 
> Otherwise it can be just like:
> 
> case MODULE_CHECK ... MAX_CHECK :

Yes, my test program compiled fine with clang.  Similar usage exists in
the kernel (eg. fs/afs/callback.c).

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 19/22] ima: support for kexec image and initramfs

2016-02-10 Thread Mimi Zohar
On Wed, 2016-02-10 at 23:09 +0200, Dmitry Kasatkin wrote:
> On Wed, Feb 3, 2016 at 9:06 PM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > Add IMA policy support for measuring/appraising the kexec image and
> > initramfs.
> >
> > Moving the enumeration to the vfs layer simplified the patches, allowing
> > the IMA changes, for the most part, to be separated from the other
> > changes.  Unfortunately, passing either a kernel_read_file_id or a
> > ima_hooks enumeration within IMA is messy.
> >
> > Option 1: duplicate kernel_read_file enumeration in ima_hooks
> >
> > enum kernel_read_file_id {
> > ...
> > READING_KEXEC_IMAGE,
> > READING_KEXEC_INITRAMFS,
> > READING_MAX_ID
> >
> > enum ima_hooks {
> > ...
> > KEXEC_CHECK
> > INITRAMFS_CHECK
> >
> > Option 2: define ima_hooks as extension of kernel_read_file
> > eg: enum ima_hooks {
> > FILE_CHECK = READING_MAX_ID,
> > MMAP_CHECK,
> >
> > In order to pass both kernel_read_file_id and ima_hooks values, we
> > would need to specify a struct containing a union.
> >
> > struct caller_id {
> > union {
> > enum ima_hooks func_id;
> > enum kernel_read_file_id read_id;
> > };
> > };
> >
> > Option 3: incorportate the ima_hooks enumeration into kernel_read_file_id,
> > perhaps changing the enumeration name.
> >
> > For now, duplicate the new READING_KEXEC_IMAGE/INITRAMFS in ima_hooks.
> >
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> > ---
> >  Documentation/ABI/testing/ima_policy |  2 +-
> >  security/integrity/ima/ima.h |  2 ++
> >  security/integrity/ima/ima_main.c| 19 ---
> >  security/integrity/ima/ima_policy.c  | 13 -
> >  4 files changed, 31 insertions(+), 5 deletions(-)
> >
> > diff --git a/Documentation/ABI/testing/ima_policy 
> > b/Documentation/ABI/testing/ima_policy
> > index 0a378a8..e80f767 100644
> > --- a/Documentation/ABI/testing/ima_policy
> > +++ b/Documentation/ABI/testing/ima_policy
> > @@ -26,7 +26,7 @@ Description:
> > option: [[appraise_type=]] [permit_directio]
> >
> > base:   func:= 
> > [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
> > -   [FIRMWARE_CHECK]
> > +   [FIRMWARE_CHECK] [KEXEC_CHECK] 
> > [INITRAMFS_CHECK]
> > mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
> >[[^]MAY_EXEC]
> > fsmagic:= hex value
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index a5d2592..832e62a 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -147,6 +147,8 @@ enum ima_hooks {
> > POST_SETATTR,
> > MODULE_CHECK,
> > FIRMWARE_CHECK,
> > +   KEXEC_CHECK,
> > +   INITRAMFS_CHECK,
> > MAX_CHECK
> >  };
> >
> > diff --git a/security/integrity/ima/ima_main.c 
> > b/security/integrity/ima/ima_main.c
> > index 1e91d94..ccf9526 100644
> > --- a/security/integrity/ima/ima_main.c
> > +++ b/security/integrity/ima/ima_main.c
> > @@ -355,7 +355,7 @@ int ima_read_file(struct file *file, enum 
> > kernel_read_file_id read_id)
> >  int ima_post_read_file(struct file *file, void *buf, loff_t size,
> >enum kernel_read_file_id read_id)
> >  {
> > -   enum ima_hooks func = FILE_CHECK;
> > +   enum ima_hooks func;
> >
> > if (!file && read_id == READING_FIRMWARE) {
> > if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
> > @@ -373,10 +373,23 @@ int ima_post_read_file(struct file *file, void *buf, 
> > loff_t size,
> > return 0;
> > }
> >
> > -   if (read_id == READING_FIRMWARE)
> > +   switch (read_id) {
> > +   case READING_FIRMWARE:
> > func = FIRMWARE_CHECK;
> > -   else if (read_id == READING_MODULE)
> > +   break;
> > +   case READING_MODULE:
> > func = MODULE_CHECK;
> > +   break;
> > +   case READING_KEXEC_IMAGE:
> > +   func = KEXEC_CHECK;
> > +   break;
> > +   case READING_KEXEC_INITRAMFS:
> > +   func = INITRAMFS_CH

Re: [PATCH v3 19/22] ima: support for kexec image and initramfs

2016-02-10 Thread Mimi Zohar
On Thu, 2016-02-11 at 01:55 +0200, Dmitry Kasatkin wrote:
> On Feb 11, 2016 1:22 AM, "Mimi Zohar" <zo...@linux.vnet.ibm.com> wrote:
> >
> > On Wed, 2016-02-10 at 23:09 +0200, Dmitry Kasatkin wrote:
> > > On Wed, Feb 3, 2016 at 9:06 PM, Mimi Zohar <zo...@linux.vnet.ibm.com>
> wrote:

> > > >
> > > > -   if (read_id == READING_FIRMWARE)
> > > > +   switch (read_id) {
> > > > +   case READING_FIRMWARE:
> > > > func = FIRMWARE_CHECK;
> > > > -   else if (read_id == READING_MODULE)
> > > > +   break;
> > > > +   case READING_MODULE:
> > > > func = MODULE_CHECK;
> > > > +   break;
> > > > +   case READING_KEXEC_IMAGE:
> > > > +   func = KEXEC_CHECK;
> > > > +   break;
> > > > +   case READING_KEXEC_INITRAMFS:
> > > > +   func = INITRAMFS_CHECK;
> > > > +   break;
> > > > +   default:
> > > > +   func = FILE_CHECK;
> > > > +   break;
> > > > +   }
> > > >
> > >
> > > I would define a separate function like "int ima_read_id_to_func(id)"
> > > which search over the map
> > >
> > > Something like...
> > >
> > > struct
> > > {
> > >  int id;
> > >  int func;
> > > }  map[] = {
> > >   { .id = READING_FIRMWARE, .fun = FIRMWARE_CHECK },
> > >...
> > >   { -1, 0 }
> > > };
> > >
> >
> > So we stay with the duplication (option 1), but clean it up.  That works
> > for me.
> >
> 
> Actually it may be simpler.
> Just define int idmap[MAX_ID] and assign to every id corresponding func.
> It will be quick and simple.

Unlike the ima_read_id_to_func() above or the original switch/case
statement, this method assumes the kernel_read_file_id enumeration stays
in sync with ima_hooks.  In terms of the  ima_read_id_to_func()
function, it would iterate over the map[] to find the corresponding .id,
whereas the current switch/case is a direct lookup.

Perhaps we should defer making a change for now.
  
Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 20/22] ima: load policy using path

2016-02-08 Thread Mimi Zohar
On Mon, 2016-02-08 at 10:45 +, Dmitry Kasatkin wrote:

> > > @@ -286,9 +322,12 @@ static ssize_t ima_write_policy(struct file *file, 
> > > const char __user *buf,
> > >   result = mutex_lock_interruptible(_write_mutex);
> > >   if (result < 0)
> > >   goto out_free;
> > > - result = ima_parse_add_rule(data);
> > > - mutex_unlock(_write_mutex);
> > >
> > > + if (data[0] == '/')
> >
> > >It seems that if we feed relative path to ima_policy the update will 
> > >fail...
> >
> > Yes, i think it is always a good idea to pass absolute path.
> 
> What if we at least emit a warning so people know what's wrong?

The next patch "ima: measure and appraise the IMA policy itself" adds
the following.  Is a failure message enough?

+   else if (ima_appraise & IMA_APPRAISE_POLICY) {
+   pr_err("IMA: signed policy required\n");
+   integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
+   "policy_update", "signed policy
required",
+   1, 0);
+   if (ima_appraise & IMA_APPRAISE_ENFORCE)
+   result = -EACCES;
+   } else
result = ima_parse_add_rule(data);

> 
> Petko
> 
> DK: May be a good idea to print that loading policy by path or not.

Are we including the pathname?  Are you suggesting a log or audit
message?

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 19/22] ima: support for kexec image and initramfs

2016-02-08 Thread Mimi Zohar
On Sun, 2016-02-07 at 22:10 +0200, Petko Manolov wrote:
> On 16-02-03 14:06:27, Mimi Zohar wrote:
 
> > Option 3: incorportate the ima_hooks enumeration into kernel_read_file_id,
> > perhaps changing the enumeration name.
> > 
> > For now, duplicate the new READING_KEXEC_IMAGE/INITRAMFS in ima_hooks.
> > 
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> 
> Option 3 seems the right way to go, but for now:

I'm just not sure.  The kernel_read_file_id enumeration is in
.

> Acked-by: Petko Manolov <pet...@mip-labs.com>

Thank you.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 16/22] module: replace copy_module_from_fd with kernel version

2016-02-04 Thread Mimi Zohar
On Thu, 2016-02-04 at 20:56 +0100, Luis R. Rodriguez wrote:
> On Wed, Feb 03, 2016 at 02:06:24PM -0500, Mimi Zohar wrote:
> > Replace copy_module_from_fd() with kernel_read_file_from_fd().
> > 
> > Although none of the upstreamed LSMs define a kernel_module_from_file
> > hook, IMA is called, based on policy, to prevent unsigned kernel modules
> > from being loaded by the original kernel module syscall and to
> > measure/appraise signed kernel modules.
> > 
> > The security function security_kernel_module_from_file() was called prior
> > to reading a kernel module.  Preventing unsigned kernel modules from being
> > loaded by the original kernel module syscall remains on the pre-read
> > kernel_read_file() security hook.  Instead of reading the kernel module
> > twice, once for measuring/appraising and again for loading the kernel
> > module, the signature validation is moved to the kernel_post_read_file()
> > security hook.
> > 
> > This patch removes the security_kernel_module_from_file() hook and security
> > call.
> > 
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> 
> Acked-by: Luis R. Rodriguez <mcg...@kernel.org>

Thank you for reviewing the patches!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3 00/22] vfs: support for a common kernel file loader

2016-02-04 Thread Mimi Zohar
On Thu, 2016-02-04 at 10:15 -0800, Kees Cook wrote:
> On Wed, Feb 3, 2016 at 11:06 AM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > For a while it was looked down upon to directly read files from Linux.
> > These days there exists a few mechanisms in the kernel that do just this
> > though to load a file into a local buffer. There are minor but important
> > checks differences on each, we should take all the best practices from
> > each of them, generalize them and make all places in the kernel that
> > read a file use it.[1]
> >
> > One difference is the method for opening the file.  In some cases we
> > have a file, while in other cases we have a pathname or a file descriptor.
> >
> > Another difference is the security hook calls, or lack of them.  In
> > some versions there is a post file read hook, while in others there
> > is a pre file read hook.
> >
> > This patch set attempts to resolve these differences.  It does not attempt
> > to merge the different methods of opening a file, but defines a single
> > common kernel file read function with two wrappers. In addition, as none
> > of the upstreamed LSMs define either a kernel_module_from_file or a
> > kernel_fw_from_file hook, this patch set removes these hooks and the
> > associated functions.  The ima_module_check() and ima_fw_from_file()
> > functions are renamed and called from the pre and post kernel_read_file
> > security functions respectively.
> 
> I'm very happy about the pre and post hooks; this solves the primary
> problem I'd had when comparing the firmware and module hooks. Thanks!

Thank you for reviewing the patches!  

> Once this series is in -next, I'll resend my rebased "loadpin" LSM.

I was looking for this reference, when writing the patch description for
modules, but couldn't remember it.  Commit 2e72d51 "security: introduce
kernel_module_from_file hook" patch description references Chrome OS. 

Thanks!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [PATCH v3.1] firmware: clean up filesystem load exit path

2016-02-04 Thread Mimi Zohar
On Thu, 2016-02-04 at 23:01 +0100, Luis R. Rodriguez wrote:
> On Thu, Feb 04, 2016 at 01:15:02PM -0800, Kees Cook wrote:
> > This makes the error and success paths more readable while trying to
> > load firmware from the filesystem.
> >
> > Signed-off-by: Kees Cook <keesc...@chromium.org>
> > Cc: Josh Boyer <jwbo...@fedoraproject.org>
> > Cc: David Howells <dhowe...@redhat.com>
> > Cc: Luis R. Rodriguez <mcg...@kernel.org>
> > Cc: Mimi Zohar <zo...@linux.vnet.ibm.com>
> 
> Thanks,
> 
> Acked-by: Luis R. Rodriguez <mcg...@kernel.org>
> 
> > ---
> > Suggested as an alternative to "[PATCH v3 06/22] firmware: fold successful 
> > fw read early"
> 
> Mimi, feel free to pick up as a replacement in your series.

Ok, thanks!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 04/22] firmware: simplify dev_*() print messages for generic helpers

2016-02-04 Thread Mimi Zohar
From: "Luis R. Rodriguez" <mcg...@kernel.org>

Simplify a few of the *generic* shared dev_warn() and dev_dbg()
print messages for three reasons:

0) Historically firmware_class code was added to help
   get device driver firmware binaries but these days
   request_firmware*() helpers are being repurposed for
   general *system data* needed by the kernel.

1) This will also help generalize shared code as much as possible
   later in the future in consideration for a new extensible firmware
   API which will enable to separate usermode helper code out as much
   as possible.

2) Kees Cook pointed out the the prints already have the device
   associated as dev_*() helpers are used, that should help identify
   the user and case in which the helpers are used. That should provide
   enough context and simplifies the messages further.

v4: generalize debug/warn messages even further as suggested by
Kees Cook.

Cc: Rusty Russell <ru...@rustcorp.com.au>
Cc: Andrew Morton <a...@linux-foundation.org>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Cc: David Howells <dhowe...@redhat.com>
Cc: Kees Cook <keesc...@chromium.org>
Cc: Casey Schaufler <ca...@schaufler-ca.com>
Cc: Ming Lei <ming@canonical.com>
Cc: Takashi Iwai <ti...@suse.de>
Cc: Vojtěch Pavlík <vojt...@suse.cz>
Cc: Kyle McMartin <k...@kernel.org>
Cc: Matthew Garrett <mj...@srcf.ucam.org>
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Luis R. Rodriguez <mcg...@kernel.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 drivers/base/firmware_class.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 8524450..3358f5d 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -353,15 +353,15 @@ static int fw_get_filesystem_firmware(struct device 
*device,
rc = fw_read_file_contents(file, buf);
fput(file);
if (rc)
-   dev_warn(device, "firmware, attempted to load %s, but 
failed with error %d\n",
-   path, rc);
+   dev_warn(device, "loading %s failed with error %d\n",
+path, rc);
else
break;
}
__putname(path);
 
if (!rc) {
-   dev_dbg(device, "firmware: direct-loading firmware %s\n",
+   dev_dbg(device, "direct-loading %s\n",
buf->fw_id);
mutex_lock(_lock);
set_bit(FW_STATUS_DONE, >status);
@@ -1051,7 +1051,7 @@ _request_firmware_prepare(struct firmware **firmware_p, 
const char *name,
}
 
if (fw_get_builtin_firmware(firmware, name)) {
-   dev_dbg(device, "firmware: using built-in firmware %s\n", name);
+   dev_dbg(device, "using built-in %s\n", name);
return 0; /* assigned */
}
 
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 07/22] vfs: define a generic function to read a file from the kernel

2016-02-03 Thread Mimi Zohar
For a while it was looked down upon to directly read files from Linux.
These days there exists a few mechanisms in the kernel that do just
this though to load a file into a local buffer.  There are minor but
important checks differences on each.  This patch set is the first
attempt at resolving some of these differences.

This patch introduces a common function for reading files from the kernel
with the corresponding security post-read hook and function.

Changelog v3:
- additional bounds checking - Luis
v2:
- To simplify patch review, re-ordered patches

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
Reviewed-by: Luis R. Rodriguez <mcg...@suse.com>
---
 fs/exec.c | 53 +++
 include/linux/fs.h|  1 +
 include/linux/lsm_hooks.h |  9 
 include/linux/security.h  |  7 +++
 security/security.c   |  7 +++
 5 files changed, 77 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index b06623a..742de7a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -56,6 +56,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -831,6 +832,58 @@ int kernel_read(struct file *file, loff_t offset,
 
 EXPORT_SYMBOL(kernel_read);
 
+int kernel_read_file(struct file *file, void **buf, loff_t *size,
+loff_t max_size)
+{
+   loff_t i_size, pos;
+   ssize_t bytes = 0;
+   int ret;
+
+   if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
+   return -EINVAL;
+
+   i_size = i_size_read(file_inode(file));
+   if (max_size > 0 && i_size > max_size)
+   return -EFBIG;
+   if (i_size <= 0)
+   return -EINVAL;
+
+   *buf = vmalloc(i_size);
+   if (!*buf)
+   return -ENOMEM;
+
+   pos = 0;
+   while (pos < i_size) {
+   bytes = kernel_read(file, pos, (char *)(*buf) + pos,
+   i_size - pos);
+   if (bytes < 0) {
+   ret = bytes;
+   goto out;
+   }
+
+   if (bytes == 0)
+   break;
+   pos += bytes;
+   }
+
+   if (pos != i_size) {
+   ret = -EIO;
+   goto out;
+   }
+
+   ret = security_kernel_post_read_file(file, *buf, i_size);
+   if (!ret)
+   *size = pos;
+
+out:
+   if (ret < 0) {
+   vfree(*buf);
+   *buf = NULL;
+   }
+   return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file);
+
 ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t 
len)
 {
ssize_t res = vfs_read(file, (void __user *)addr, len, );
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 3aa5142..93ca379 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2527,6 +2527,7 @@ static inline void i_readcount_inc(struct inode *inode)
 extern int do_pipe_flags(int *, int);
 
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
+extern int kernel_read_file(struct file *, void **, loff_t *, loff_t);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 71969de..f82631c 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -561,6 +561,13 @@
  * the kernel module to load. If the module is being loaded from a blob,
  * this argument will be NULL.
  * Return 0 if permission is granted.
+ * @kernel_post_read_file:
+ * Read a file specified by userspace.
+ * @file contains the file structure pointing to the file being read
+ * by the kernel.
+ * @buf pointer to buffer containing the file contents.
+ * @size length of the file contents.
+ * Return 0 if permission is granted.
  * @task_fix_setuid:
  * Update the module's state after setting one or more of the user
  * identity attributes of the current process.  The @flags parameter
@@ -1457,6 +1464,7 @@ union security_list_options {
int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file);
+   int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size);
int (*task_fix_setuid)(struct cred *new, const struct cred *old,
int flags);
int (*task_setpgid)(struct task_struct *p, pid_t pgid);
@@ -1716,6 +1724,7 @@ struct security_hook_heads {
struct list_head kernel_act_as;
struct list_head kernel_create_files_as;
struct list_head kernel_fw_from_file;
+   struct list_head kernel_post_read_file;
struct list_head kernel_module_request;
struct list_head kernel_module_from_fi

[PATCH v3 12/22] vfs: define kernel_read_file_from_path

2016-02-03 Thread Mimi Zohar
This patch defines kernel_read_file_from_path(), a wrapper for the VFS
common kernel_read_file().

Changelog:
- Separated from the IMA patch

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 fs/exec.c  | 22 ++
 include/linux/fs.h |  2 ++
 2 files changed, 24 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index cd2b5b2..5629958 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -884,6 +884,28 @@ out:
 }
 EXPORT_SYMBOL_GPL(kernel_read_file);
 
+int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
+  loff_t max_size, enum kernel_read_file_id id)
+{
+   struct file *file;
+   int ret;
+
+   if (!path || !*path)
+   return -EINVAL;
+
+   file = filp_open(path, O_RDONLY, 0);
+   if (IS_ERR(file)) {
+   ret = PTR_ERR(file);
+   pr_err("Unable to open file: %s (%d)", path, ret);
+   return ret;
+   }
+
+   ret = kernel_read_file(file, buf, size, max_size, id);
+   fput(file);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
+
 ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t 
len)
 {
ssize_t res = vfs_read(file, (void __user *)addr, len, );
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1458ca5..962c491 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2533,6 +2533,8 @@ enum kernel_read_file_id {
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
 extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
enum kernel_read_file_id);
+extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
+ enum kernel_read_file_id);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 15/22] vfs: define kernel_copy_file_from_fd()

2016-02-03 Thread Mimi Zohar
This patch defines kernel_read_file_from_fd(), a wrapper for the VFS
common kernel_read_file().

Changelog:
- Separated from the kernel modules patch

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 fs/exec.c  | 16 
 include/linux/fs.h |  2 ++
 2 files changed, 18 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index 1d39c4e..f3a0ce2 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -910,6 +910,22 @@ int kernel_read_file_from_path(char *path, void **buf, 
loff_t *size,
 }
 EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
 
+int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
+enum kernel_read_file_id id)
+{
+   struct fd f = fdget(fd);
+   int ret = -EBADF;
+
+   if (!f.file)
+   goto out;
+
+   ret = kernel_read_file(f.file, buf, size, max_size, id);
+out:
+   fdput(f);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
+
 ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t 
len)
 {
ssize_t res = vfs_read(file, (void __user *)addr, len, );
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 2a9670a..5ba806b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2536,6 +2536,8 @@ extern int kernel_read_file(struct file *, void **, 
loff_t *, loff_t,
enum kernel_read_file_id);
 extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
  enum kernel_read_file_id);
+extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
+   enum kernel_read_file_id);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 09/22] ima: provide buffer hash calculation function

2016-02-03 Thread Mimi Zohar
From: Dmitry Kasatkin <d.kasat...@samsung.com>

This patch provides convenient buffer hash calculation function.

Changelog v3:
- fix while hash calculation - Dmitry
v1:
- rewrite to support loff_t sized buffers - Mimi
  (based on Fenguang Wu's testing)

Signed-off-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h|  2 ++
 security/integrity/ima/ima_crypto.c | 47 +
 2 files changed, 49 insertions(+)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index b7e7935..2c5262f 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -107,6 +107,8 @@ int ima_add_template_entry(struct ima_template_entry 
*entry, int violation,
   const char *op, struct inode *inode,
   const unsigned char *filename);
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash);
 int ima_calc_field_array_hash(struct ima_field_data *field_data,
  struct ima_template_desc *desc, int num_fields,
  struct ima_digest_data *hash);
diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index fb30ce4..fccb6ce 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -519,6 +519,53 @@ int ima_calc_field_array_hash(struct ima_field_data 
*field_data,
return rc;
 }
 
+static int calc_buffer_shash_tfm(const void *buf, loff_t size,
+   struct ima_digest_data *hash,
+   struct crypto_shash *tfm)
+{
+   SHASH_DESC_ON_STACK(shash, tfm);
+   unsigned int len;
+   int rc;
+
+   shash->tfm = tfm;
+   shash->flags = 0;
+
+   hash->length = crypto_shash_digestsize(tfm);
+
+   rc = crypto_shash_init(shash);
+   if (rc != 0)
+   return rc;
+
+   while (size) {
+   len = size < PAGE_SIZE ? size : PAGE_SIZE;
+   rc = crypto_shash_update(shash, buf, len);
+   if (rc)
+   break;
+   buf += len;
+   size -= len;
+   }
+
+   if (!rc)
+   rc = crypto_shash_final(shash, hash->digest);
+   return rc;
+}
+
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   struct crypto_shash *tfm;
+   int rc;
+
+   tfm = ima_alloc_tfm(hash->algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   rc = calc_buffer_shash_tfm(buf, len, hash, tfm);
+
+   ima_free_tfm(tfm);
+   return rc;
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
if (!ima_used_chip)
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 05/22] firmware: move completing fw into a helper

2016-02-03 Thread Mimi Zohar
From: "Luis R. Rodriguez" <mcg...@kernel.org>

This will be re-used later through a new extensible interface.

Reviewed-by: Josh Boyer <jwbo...@fedoraproject.org>
Signed-off-by: Luis R. Rodriguez <mcg...@kernel.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 drivers/base/firmware_class.c | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 3358f5d..fb64814 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -322,6 +322,15 @@ fail:
return rc;
 }
 
+static void fw_finish_direct_load(struct device *device,
+ struct firmware_buf *buf)
+{
+   mutex_lock(_lock);
+   set_bit(FW_STATUS_DONE, >status);
+   complete_all(>completion);
+   mutex_unlock(_lock);
+}
+
 static int fw_get_filesystem_firmware(struct device *device,
   struct firmware_buf *buf)
 {
@@ -363,10 +372,7 @@ static int fw_get_filesystem_firmware(struct device 
*device,
if (!rc) {
dev_dbg(device, "direct-loading %s\n",
buf->fw_id);
-   mutex_lock(_lock);
-   set_bit(FW_STATUS_DONE, >status);
-   complete_all(>completion);
-   mutex_unlock(_lock);
+   fw_finish_direct_load(device, buf);
}
 
return rc;
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 00/22] vfs: support for a common kernel file loader

2016-02-03 Thread Mimi Zohar
For a while it was looked down upon to directly read files from Linux.
These days there exists a few mechanisms in the kernel that do just this
though to load a file into a local buffer. There are minor but important
checks differences on each, we should take all the best practices from
each of them, generalize them and make all places in the kernel that
read a file use it.[1]

One difference is the method for opening the file.  In some cases we
have a file, while in other cases we have a pathname or a file descriptor.

Another difference is the security hook calls, or lack of them.  In
some versions there is a post file read hook, while in others there
is a pre file read hook. 

This patch set attempts to resolve these differences.  It does not attempt
to merge the different methods of opening a file, but defines a single
common kernel file read function with two wrappers. In addition, as none
of the upstreamed LSMs define either a kernel_module_from_file or a
kernel_fw_from_file hook, this patch set removes these hooks and the
associated functions.  The ima_module_check() and ima_fw_from_file()
functions are renamed and called from the pre and post kernel_read_file
security functions respectively.

Changelog:
- Rebased on top of some of the "firmware_class: extensible firmware API"
patches posted by Luis.
- Removed the kernel_module_from_file and kernel_fw_from_file security
hooks and functions.
- Defined "kernel_read_file_id" enumeration, independently of "ima_hooks".
- Split patches for ease of review.

The latest version of these patches can be found in the next-kernel-read-v3
branch of:
git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git

[1] Taken from Luis Rodriguez's wiki -
http://kernelnewbies.org/KernelProjects/common-kernel-loader

Mimi

David Howells (1):
  firmware: fold successful fw read early

Dmitry Kasatkin (3):
  ima: separate 'security.ima' reading functionality from collect
  ima: provide buffer hash calculation function
  ima: load policy using path

Luis R. Rodriguez (2):
  firmware: simplify dev_*() print messages for generic helpers
  firmware: move completing fw into a helper

Mimi Zohar (16):
  ima: refactor ima_policy_show() to display "ima_hooks" rules
  ima: use "ima_hooks" enum as function argument
  vfs: define a generic function to read a file from the kernel
  vfs: define kernel_read_file_id enumeration
  ima: calculate the hash of a buffer using aynchronous hash(ahash)
  ima: define a new hook to measure and appraise a file already in
memory
  vfs: define kernel_read_file_from_path
  firmware: replace call to fw_read_file_contents() with kernel version
  security: define kernel_read_file hook
  vfs: define kernel_copy_file_from_fd()
  module: replace copy_module_from_fd with kernel version
  ima: remove firmware and module specific cached status info
  kexec: replace call to copy_file_from_fd() with kernel version
  ima: support for kexec image and initramfs
  ima: measure and appraise the IMA policy itself
  ima: require signed IMA policy

 Documentation/ABI/testing/ima_policy  |   2 +-
 drivers/base/firmware_class.c |  76 ++-
 fs/exec.c |  95 +++
 include/linux/fs.h|  15 
 include/linux/ima.h   |  10 ++-
 include/linux/lsm_hooks.h |  35 -
 include/linux/security.h  |  16 ++--
 kernel/kexec_file.c   |  73 +++---
 kernel/module.c   |  68 ++---
 security/integrity/iint.c |   4 +-
 security/integrity/ima/ima.h  |  49 
 security/integrity/ima/ima_api.c  |  25 +++
 security/integrity/ima/ima_appraise.c |  69 -
 security/integrity/ima/ima_crypto.c   | 120 +-
 security/integrity/ima/ima_fs.c   |  50 -
 security/integrity/ima/ima_init.c |   2 +-
 security/integrity/ima/ima_main.c | 104 +++---
 security/integrity/ima/ima_policy.c   | 107 +-
 security/integrity/ima/ima_template.c |   2 -
 security/integrity/ima/ima_template_lib.c |   1 -
 security/integrity/integrity.h|  15 ++--
 security/security.c   |  32 
 22 files changed, 605 insertions(+), 365 deletions(-)

-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 08/22] vfs: define kernel_read_file_id enumeration

2016-02-03 Thread Mimi Zohar
To differentiate between the kernel_read_file() callers, this patch
defines a new enumeration named kernel_read_file_id and includes the
caller identifier as an argument.

Subsequent patches define READING_KEXEC_IMAGE, READING_KEXEC_INITRAMFS,
READING_FIRMWARE, READING_MODULE, and READING_POLICY.

Changelog v3:
- Replace the IMA specific enumeration with a generic one.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 fs/exec.c | 4 ++--
 include/linux/fs.h| 7 ++-
 include/linux/lsm_hooks.h | 4 +++-
 include/linux/security.h  | 7 +--
 security/security.c   | 5 +++--
 5 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 742de7a..cd2b5b2 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -833,7 +833,7 @@ int kernel_read(struct file *file, loff_t offset,
 EXPORT_SYMBOL(kernel_read);
 
 int kernel_read_file(struct file *file, void **buf, loff_t *size,
-loff_t max_size)
+loff_t max_size, enum kernel_read_file_id id)
 {
loff_t i_size, pos;
ssize_t bytes = 0;
@@ -871,7 +871,7 @@ int kernel_read_file(struct file *file, void **buf, loff_t 
*size,
goto out;
}
 
-   ret = security_kernel_post_read_file(file, *buf, i_size);
+   ret = security_kernel_post_read_file(file, *buf, i_size, id);
if (!ret)
*size = pos;
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 93ca379..1458ca5 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2526,8 +2526,13 @@ static inline void i_readcount_inc(struct inode *inode)
 #endif
 extern int do_pipe_flags(int *, int);
 
+enum kernel_read_file_id {
+   READING_MAX_ID
+};
+
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
-extern int kernel_read_file(struct file *, void **, loff_t *, loff_t);
+extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
+   enum kernel_read_file_id);
 extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
 extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
 extern struct file * open_exec(const char *);
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index f82631c..2337f33 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -567,6 +567,7 @@
  * by the kernel.
  * @buf pointer to buffer containing the file contents.
  * @size length of the file contents.
+ * @id kernel read file identifier
  * Return 0 if permission is granted.
  * @task_fix_setuid:
  * Update the module's state after setting one or more of the user
@@ -1464,7 +1465,8 @@ union security_list_options {
int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file);
-   int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size);
+   int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
+enum kernel_read_file_id id);
int (*task_fix_setuid)(struct cred *new, const struct cred *old,
int flags);
int (*task_setpgid)(struct task_struct *p, pid_t pgid);
diff --git a/include/linux/security.h b/include/linux/security.h
index f30f564..b68ce94 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct linux_binprm;
 struct cred;
@@ -301,7 +302,8 @@ int security_kernel_create_files_as(struct cred *new, 
struct inode *inode);
 int security_kernel_fw_from_file(struct file *file, char *buf, size_t size);
 int security_kernel_module_request(char *kmod_name);
 int security_kernel_module_from_file(struct file *file);
-int security_kernel_post_read_file(struct file *file, char *buf, loff_t size);
+int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
+  enum kernel_read_file_id id);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
 int flags);
 int security_task_setpgid(struct task_struct *p, pid_t pgid);
@@ -868,7 +870,8 @@ static inline int security_kernel_module_from_file(struct 
file *file)
 }
 
 static inline int security_kernel_post_read_file(struct file *file,
-char *buf, loff_t size)
+char *buf, loff_t size,
+enum kernel_read_file_id id)
 {
return 0;
 }
diff --git a/security/security.c b/security/security.c
index ae50730..796a261 100644
--- a/security/security.c
+++ b/security/security.c
@@ -910,9 +910,10 @@ int security_kernel_module_from_file(struct file *file)
return ima_module_check(file);
 }
 
-int security_kernel_post_read_file(struc

[PATCH v3 01/22] ima: separate 'security.ima' reading functionality from collect

2016-02-03 Thread Mimi Zohar
From: Dmitry Kasatkin <d.kasat...@samsung.com>

Instead of passing pointers to pointers to ima_collect_measurent() to
read and return the 'security.ima' xattr value, this patch moves the
functionality to the calling process_measurement() to directly read
the xattr and pass only the hash algo to the ima_collect_measurement().

Signed-off-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h  | 15 +++
 security/integrity/ima/ima_api.c  | 15 +++
 security/integrity/ima/ima_appraise.c | 25 ++---
 security/integrity/ima/ima_crypto.c   |  2 +-
 security/integrity/ima/ima_init.c |  2 +-
 security/integrity/ima/ima_main.c | 11 +++
 security/integrity/ima/ima_template.c |  2 --
 security/integrity/ima/ima_template_lib.c |  1 -
 8 files changed, 33 insertions(+), 40 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 585af61..fb8da36 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "../integrity.h"
 
@@ -140,9 +141,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
 int ima_get_action(struct inode *inode, int mask, int function);
 int ima_must_measure(struct inode *inode, int mask, int function);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file,
-   struct evm_ima_xattr_data **xattr_value,
-   int *xattr_len);
+   struct file *file, enum hash_algo algo);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file 
*file,
   const unsigned char *filename,
   struct evm_ima_xattr_data *xattr_value,
@@ -188,8 +187,8 @@ int ima_must_appraise(struct inode *inode, int mask, enum 
ima_hooks func);
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
   int func);
-void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
-  struct ima_digest_data *hash);
+enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+int xattr_len);
 int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
 
@@ -221,10 +220,10 @@ static inline enum integrity_status 
ima_get_cache_status(struct integrity_iint_c
return INTEGRITY_UNKNOWN;
 }
 
-static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
-int xattr_len,
-struct ima_digest_data *hash)
+static inline enum hash_algo
+ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len)
 {
+   return ima_hash_algo;
 }
 
 static inline int ima_read_xattr(struct dentry *dentry,
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1d950fb..e7c7a5d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -18,7 +18,7 @@
 #include 
 #include 
 #include 
-#include 
+
 #include "ima.h"
 
 /*
@@ -188,9 +188,7 @@ int ima_get_action(struct inode *inode, int mask, int 
function)
  * Return 0 on success, error code otherwise
  */
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file,
-   struct evm_ima_xattr_data **xattr_value,
-   int *xattr_len)
+   struct file *file, enum hash_algo algo)
 {
const char *audit_cause = "failed";
struct inode *inode = file_inode(file);
@@ -201,9 +199,6 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
char digest[IMA_MAX_DIGEST_SIZE];
} hash;
 
-   if (xattr_value)
-   *xattr_len = ima_read_xattr(file->f_path.dentry, xattr_value);
-
if (!(iint->flags & IMA_COLLECTED)) {
u64 i_version = file_inode(file)->i_version;
 
@@ -213,11 +208,7 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
goto out;
}
 
-   /* use default hash algorithm */
-   hash.hdr.algo = ima_hash_algo;
-
-   if (xattr_value)
-   ima_get_hash_algo(*xattr_value, *xattr_len, );
+   hash.hdr.algo = algo;
 
result = ima_calc_file_hash(file, );
if (!result) {
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 1873b55..9c2b46b 100644
--- a/security/integrity/ima/ima_ap

[PATCH v3 18/22] kexec: replace call to copy_file_from_fd() with kernel version

2016-02-03 Thread Mimi Zohar
Replace copy_file_from_fd() with kernel_read_file_from_fd().

Two new identifiers named READING_KEXEC_IMAGE and READING_KEXEC_INITRAMFS
are defined for measuring, appraising or auditing the kexec image and
initramfs.

Changelog v3:
- return -EBADF, not -ENOEXEC
- identifier change
- moved copy_file_from_fd() to a separate patch
- defer support for IMA
v1:
- re-order and squash the kexec patches
v0: ima: measure and appraise kexec image and initramfs (squashed)
- rename ima_read_hooks enumeration to ima_policy_id
- use kstat file size type loff_t, not size_t
- add union name "hooks" to fix sparse warning
- Calculate the file hash from the in memory buffer
(suggested by Dave Young)
- Rename ima_read_and_process_file() to ima_hash_and_process_file()
- replace individual case statements with range:
KEXEC_CHECK ... IMA_MAX_READ_CHECK - 1
- Instead of ima_read_and_process_file() allocating memory, the caller
allocates and frees the memory.
- Moved the kexec measurement/appraisal call to copy_file_from_fd(). The
same call now measures and appraises both the kexec image and initramfs.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/fs.h  |  2 ++
 kernel/kexec_file.c | 73 +++--
 2 files changed, 11 insertions(+), 64 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9e1f1e3..d4d556e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2529,6 +2529,8 @@ extern int do_pipe_flags(int *, int);
 enum kernel_read_file_id {
READING_FIRMWARE = 1,
READING_MODULE,
+   READING_KEXEC_IMAGE,
+   READING_KEXEC_INITRAMFS,
READING_MAX_ID
 };
 
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index b70ada0..1443f93 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,65 +34,6 @@ size_t __weak kexec_purgatory_size = 0;
 
 static int kexec_calculate_store_digests(struct kimage *image);
 
-static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len)
-{
-   struct fd f = fdget(fd);
-   int ret;
-   struct kstat stat;
-   loff_t pos;
-   ssize_t bytes = 0;
-
-   if (!f.file)
-   return -EBADF;
-
-   ret = vfs_getattr(>f_path, );
-   if (ret)
-   goto out;
-
-   if (stat.size > INT_MAX) {
-   ret = -EFBIG;
-   goto out;
-   }
-
-   /* Don't hand 0 to vmalloc, it whines. */
-   if (stat.size == 0) {
-   ret = -EINVAL;
-   goto out;
-   }
-
-   *buf = vmalloc(stat.size);
-   if (!*buf) {
-   ret = -ENOMEM;
-   goto out;
-   }
-
-   pos = 0;
-   while (pos < stat.size) {
-   bytes = kernel_read(f.file, pos, (char *)(*buf) + pos,
-   stat.size - pos);
-   if (bytes < 0) {
-   vfree(*buf);
-   ret = bytes;
-   goto out;
-   }
-
-   if (bytes == 0)
-   break;
-   pos += bytes;
-   }
-
-   if (pos != stat.size) {
-   ret = -EBADF;
-   vfree(*buf);
-   goto out;
-   }
-
-   *buf_len = pos;
-out:
-   fdput(f);
-   return ret;
-}
-
 /* Architectures can provide this probe function */
 int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
 unsigned long buf_len)
@@ -180,16 +122,17 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
 {
int ret = 0;
void *ldata;
+   loff_t size;
 
-   ret = copy_file_from_fd(kernel_fd, >kernel_buf,
-   >kernel_buf_len);
+   ret = kernel_read_file_from_fd(kernel_fd, >kernel_buf,
+  , INT_MAX, READING_KEXEC_IMAGE);
if (ret)
return ret;
+   image->kernel_buf_len = size;
 
/* Call arch image probe handlers */
ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
image->kernel_buf_len);
-
if (ret)
goto out;
 
@@ -204,10 +147,12 @@ kimage_file_prepare_segments(struct kimage *image, int 
kernel_fd, int initrd_fd,
 #endif
/* It is possible that there no initramfs is being loaded */
if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
-   ret = copy_file_from_fd(initrd_fd, >initrd_buf,
-   >initrd_buf_len);
+   ret = kernel_read_file_from_fd(initrd_fd, >initrd_buf,
+  , INT_MAX,
+  READING_KEXEC_INITRAMFS);
if (ret)
   

[PATCH v3 21/22] ima: measure and appraise the IMA policy itself

2016-02-03 Thread Mimi Zohar
Add support for measuring and appraising the IMA policy itself.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h|  2 ++
 security/integrity/ima/ima_fs.c |  9 -
 security/integrity/ima/ima_main.c   |  3 +++
 security/integrity/ima/ima_policy.c | 10 +-
 4 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 832e62a..6685968 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -149,6 +149,7 @@ enum ima_hooks {
FIRMWARE_CHECK,
KEXEC_CHECK,
INITRAMFS_CHECK,
+   POLICY_CHECK,
MAX_CHECK
 };
 
@@ -191,6 +192,7 @@ int ima_policy_show(struct seq_file *m, void *v);
 #define IMA_APPRAISE_LOG   0x04
 #define IMA_APPRAISE_MODULES   0x08
 #define IMA_APPRAISE_FIRMWARE  0x10
+#define IMA_APPRAISE_POLICY0x20
 
 #ifdef CONFIG_IMA_APPRAISE
 int ima_appraise_measurement(enum ima_hooks func,
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 00ccd67..7b15e80 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -325,7 +325,14 @@ static ssize_t ima_write_policy(struct file *file, const 
char __user *buf,
 
if (data[0] == '/')
result = ima_read_policy(data);
-   else
+   else if (ima_appraise & IMA_APPRAISE_POLICY) {
+   pr_err("IMA: signed policy required\n");
+   integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
+   "policy_update", "signed policy required",
+   1, 0);
+   if (ima_appraise & IMA_APPRAISE_ENFORCE)
+   result = -EACCES;
+   } else
result = ima_parse_add_rule(data);
mutex_unlock(_write_mutex);
 out_free:
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index ccf9526..497a6f2 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -386,6 +386,9 @@ int ima_post_read_file(struct file *file, void *buf, loff_t 
size,
case READING_KEXEC_INITRAMFS:
func = INITRAMFS_CHECK;
break;
+   case READING_POLICY:
+   func = POLICY_CHECK;
+   break;
default:
func = FILE_CHECK;
break;
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index d02560e..39a811a 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -114,6 +114,7 @@ static struct ima_rule_entry default_measurement_rules[] = {
 .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
+   {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_appraise_rules[] = {
@@ -616,6 +617,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
entry->func = KEXEC_CHECK;
else if (strcmp(args[0].from, "INITRAMFS_CHECK") == 0)
entry->func = INITRAMFS_CHECK;
+   else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
+   entry->func = POLICY_CHECK;
else
result = -EINVAL;
if (!result)
@@ -774,6 +777,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry 
*entry)
temp_ima_appraise |= IMA_APPRAISE_MODULES;
else if (entry->func == FIRMWARE_CHECK)
temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
+   else if (entry->func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
audit_log_format(ab, "res=%d", !result);
audit_log_end(ab);
return result;
@@ -860,7 +865,7 @@ static char *mask_tokens[] = {
 enum {
func_file = 0, func_mmap, func_bprm,
func_module, func_firmware, func_post,
-   func_kexec, func_initramfs
+   func_kexec, func_initramfs, func_policy
 };
 
 static char *func_tokens[] = {
@@ -940,6 +945,9 @@ static void policy_func_show(struct seq_file *m, enum 
ima_hooks func)
case INITRAMFS_CHECK:
seq_printf(m, pt(Opt_func), ft(func_initramfs));
break;
+   case POLICY_CHECK:
+   seq_printf(m, pt(Opt_func), ft(func_policy));
+   break;
default:
snprintf(tbuf, sizeof(tbuf), "%d", func);
seq_printf(m, pt(Opt_func), tbuf);
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 06/22] firmware: fold successful fw read early

2016-02-03 Thread Mimi Zohar
From: David Howells <dhowe...@redhat.com>

We'll be folding in some more checks on fw_read_file_contents(),
this will make the success case easier to follow.

Reviewed-by: Josh Boyer <jwbo...@fedoraproject.org>
Signed-off-by: David Howells <dhowe...@redhat.com>
Signed-off-by: Luis R. Rodriguez <mcg...@kernel.org>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 drivers/base/firmware_class.c | 16 +++-
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index fb64814..c658cec 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -361,20 +361,18 @@ static int fw_get_filesystem_firmware(struct device 
*device,
continue;
rc = fw_read_file_contents(file, buf);
fput(file);
-   if (rc)
+   if (rc == 0) {
+   dev_dbg(device, "direct-loading %s\n",
+   buf->fw_id);
+   fw_finish_direct_load(device, buf);
+   goto out;
+   } else
dev_warn(device, "loading %s failed with error %d\n",
 path, rc);
-   else
-   break;
}
+out:
__putname(path);
 
-   if (!rc) {
-   dev_dbg(device, "direct-loading %s\n",
-   buf->fw_id);
-   fw_finish_direct_load(device, buf);
-   }
-
return rc;
 }
 
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 16/22] module: replace copy_module_from_fd with kernel version

2016-02-03 Thread Mimi Zohar
Replace copy_module_from_fd() with kernel_read_file_from_fd().

Although none of the upstreamed LSMs define a kernel_module_from_file
hook, IMA is called, based on policy, to prevent unsigned kernel modules
from being loaded by the original kernel module syscall and to
measure/appraise signed kernel modules.

The security function security_kernel_module_from_file() was called prior
to reading a kernel module.  Preventing unsigned kernel modules from being
loaded by the original kernel module syscall remains on the pre-read
kernel_read_file() security hook.  Instead of reading the kernel module
twice, once for measuring/appraising and again for loading the kernel
module, the signature validation is moved to the kernel_post_read_file()
security hook.

This patch removes the security_kernel_module_from_file() hook and security
call.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/fs.h|  1 +
 include/linux/ima.h   |  6 
 include/linux/lsm_hooks.h |  7 
 include/linux/security.h  |  5 ---
 kernel/module.c   | 68 +--
 security/integrity/ima/ima_main.c | 35 
 security/security.c   | 12 ---
 7 files changed, 22 insertions(+), 112 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5ba806b..9e1f1e3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2528,6 +2528,7 @@ extern int do_pipe_flags(int *, int);
 
 enum kernel_read_file_id {
READING_FIRMWARE = 1,
+   READING_MODULE,
READING_MAX_ID
 };
 
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 6adcaea..e6516cb 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -18,7 +18,6 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask, int opened);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
-extern int ima_module_check(struct file *file);
 extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
 extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
  enum kernel_read_file_id id);
@@ -44,11 +43,6 @@ static inline int ima_file_mmap(struct file *file, unsigned 
long prot)
return 0;
 }
 
-static inline int ima_module_check(struct file *file)
-{
-   return 0;
-}
-
 static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
 {
return 0;
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index d32b7bd..cdee11c 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -546,12 +546,6 @@
  * userspace to load a kernel module with the given name.
  * @kmod_name name of the module requested by the kernel
  * Return 0 if successful.
- * @kernel_module_from_file:
- * Load a kernel module from userspace.
- * @file contains the file structure pointing to the file containing
- * the kernel module to load. If the module is being loaded from a blob,
- * this argument will be NULL.
- * Return 0 if permission is granted.
  * @kernel_read_file:
  * Read a file specified by userspace.
  * @file contains the file structure pointing to the file being read
@@ -1725,7 +1719,6 @@ struct security_hook_heads {
struct list_head kernel_read_file;
struct list_head kernel_post_read_file;
struct list_head kernel_module_request;
-   struct list_head kernel_module_from_file;
struct list_head task_fix_setuid;
struct list_head task_setpgid;
struct list_head task_getpgid;
diff --git a/include/linux/security.h b/include/linux/security.h
index 071fb74..157f0cb 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -859,11 +859,6 @@ static inline int security_kernel_module_request(char 
*kmod_name)
return 0;
 }
 
-static inline int security_kernel_module_from_file(struct file *file)
-{
-   return 0;
-}
-
 static inline int security_kernel_read_file(struct file *file,
enum kernel_read_file_id id)
 {
diff --git a/kernel/module.c b/kernel/module.c
index 8f051a1..d77c4f1 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2665,7 +2665,7 @@ static int copy_module_from_user(const void __user *umod, 
unsigned long len,
if (info->len < sizeof(*(info->hdr)))
return -ENOEXEC;
 
-   err = security_kernel_module_from_file(NULL);
+   err = security_kernel_read_file(NULL, READING_MODULE);
if (err)
return err;
 
@@ -2683,63 +2683,6 @@ static int copy_module_from_user(const void __user 
*umod, unsigned long len,
return 0;
 }
 
-/* Sets info->hdr and info->len. */
-static int copy_module_from_fd(int fd, struct load_info *info)
-{
-   struct fd f = fdget(fd);
-   int err;
-   

[PATCH v3 14/22] security: define kernel_read_file hook

2016-02-03 Thread Mimi Zohar
The kernel_read_file security hook is called prior to reading the file
into memory.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 fs/exec.c |  4 
 include/linux/ima.h   |  6 ++
 include/linux/lsm_hooks.h |  8 
 include/linux/security.h  |  7 +++
 security/integrity/ima/ima_main.c | 16 
 security/security.c   | 12 
 6 files changed, 53 insertions(+)

diff --git a/fs/exec.c b/fs/exec.c
index 5629958..1d39c4e 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -842,6 +842,10 @@ int kernel_read_file(struct file *file, void **buf, loff_t 
*size,
if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
return -EINVAL;
 
+   ret = security_kernel_read_file(file, id);
+   if (ret)
+   return ret;
+
i_size = i_size_read(file_inode(file));
if (max_size > 0 && i_size > max_size)
return -EFBIG;
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 7aea486..6adcaea 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -19,6 +19,7 @@ extern int ima_file_check(struct file *file, int mask, int 
opened);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern int ima_module_check(struct file *file);
+extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
 extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
  enum kernel_read_file_id id);
 
@@ -48,6 +49,11 @@ static inline int ima_module_check(struct file *file)
return 0;
 }
 
+static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
+{
+   return 0;
+}
+
 static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
 enum kernel_read_file_id id)
 {
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 7d04a12..d32b7bd 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -552,6 +552,12 @@
  * the kernel module to load. If the module is being loaded from a blob,
  * this argument will be NULL.
  * Return 0 if permission is granted.
+ * @kernel_read_file:
+ * Read a file specified by userspace.
+ * @file contains the file structure pointing to the file being read
+ * by the kernel.
+ * @id kernel read file identifier
+ * Return 0 if permission is granted.
  * @kernel_post_read_file:
  * Read a file specified by userspace.
  * @file contains the file structure pointing to the file being read
@@ -1455,6 +1461,7 @@ union security_list_options {
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file);
+   int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id);
int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
 enum kernel_read_file_id id);
int (*task_fix_setuid)(struct cred *new, const struct cred *old,
@@ -1715,6 +1722,7 @@ struct security_hook_heads {
struct list_head cred_transfer;
struct list_head kernel_act_as;
struct list_head kernel_create_files_as;
+   struct list_head kernel_read_file;
struct list_head kernel_post_read_file;
struct list_head kernel_module_request;
struct list_head kernel_module_from_file;
diff --git a/include/linux/security.h b/include/linux/security.h
index cee1349..071fb74 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -302,6 +302,7 @@ int security_kernel_act_as(struct cred *new, u32 secid);
 int security_kernel_create_files_as(struct cred *new, struct inode *inode);
 int security_kernel_module_request(char *kmod_name);
 int security_kernel_module_from_file(struct file *file);
+int security_kernel_read_file(struct file *file, enum kernel_read_file_id id);
 int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
   enum kernel_read_file_id id);
 int security_task_fix_setuid(struct cred *new, const struct cred *old,
@@ -863,6 +864,12 @@ static inline int security_kernel_module_from_file(struct 
file *file)
return 0;
 }
 
+static inline int security_kernel_read_file(struct file *file,
+   enum kernel_read_file_id id)
+{
+   return 0;
+}
+
 static inline int security_kernel_post_read_file(struct file *file,
 char *buf, loff_t size,
 enum kernel_read_file_id id)
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index 4a5db31..6f79bdf 100644
--- a/security/integrity/ima/ima_main.c
+++ b/securit

[PATCH v3 19/22] ima: support for kexec image and initramfs

2016-02-03 Thread Mimi Zohar
Add IMA policy support for measuring/appraising the kexec image and
initramfs.

Moving the enumeration to the vfs layer simplified the patches, allowing
the IMA changes, for the most part, to be separated from the other
changes.  Unfortunately, passing either a kernel_read_file_id or a
ima_hooks enumeration within IMA is messy.

Option 1: duplicate kernel_read_file enumeration in ima_hooks

enum kernel_read_file_id {
...
READING_KEXEC_IMAGE,
READING_KEXEC_INITRAMFS,
READING_MAX_ID

enum ima_hooks {
...
KEXEC_CHECK
INITRAMFS_CHECK

Option 2: define ima_hooks as extension of kernel_read_file
eg: enum ima_hooks {
FILE_CHECK = READING_MAX_ID,
MMAP_CHECK,

In order to pass both kernel_read_file_id and ima_hooks values, we
would need to specify a struct containing a union.

struct caller_id {
union {
enum ima_hooks func_id;
enum kernel_read_file_id read_id;
};
};

Option 3: incorportate the ima_hooks enumeration into kernel_read_file_id,
perhaps changing the enumeration name.

For now, duplicate the new READING_KEXEC_IMAGE/INITRAMFS in ima_hooks.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 Documentation/ABI/testing/ima_policy |  2 +-
 security/integrity/ima/ima.h |  2 ++
 security/integrity/ima/ima_main.c| 19 ---
 security/integrity/ima/ima_policy.c  | 13 -
 4 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy 
b/Documentation/ABI/testing/ima_policy
index 0a378a8..e80f767 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -26,7 +26,7 @@ Description:
option: [[appraise_type=]] [permit_directio]
 
base:   func:= 
[BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
-   [FIRMWARE_CHECK]
+   [FIRMWARE_CHECK] [KEXEC_CHECK] [INITRAMFS_CHECK]
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
   [[^]MAY_EXEC]
fsmagic:= hex value
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index a5d2592..832e62a 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -147,6 +147,8 @@ enum ima_hooks {
POST_SETATTR,
MODULE_CHECK,
FIRMWARE_CHECK,
+   KEXEC_CHECK,
+   INITRAMFS_CHECK,
MAX_CHECK
 };
 
diff --git a/security/integrity/ima/ima_main.c 
b/security/integrity/ima/ima_main.c
index 1e91d94..ccf9526 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -355,7 +355,7 @@ int ima_read_file(struct file *file, enum 
kernel_read_file_id read_id)
 int ima_post_read_file(struct file *file, void *buf, loff_t size,
   enum kernel_read_file_id read_id)
 {
-   enum ima_hooks func = FILE_CHECK;
+   enum ima_hooks func;
 
if (!file && read_id == READING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
@@ -373,10 +373,23 @@ int ima_post_read_file(struct file *file, void *buf, 
loff_t size,
return 0;
}
 
-   if (read_id == READING_FIRMWARE)
+   switch (read_id) {
+   case READING_FIRMWARE:
func = FIRMWARE_CHECK;
-   else if (read_id == READING_MODULE)
+   break;
+   case READING_MODULE:
func = MODULE_CHECK;
+   break;
+   case READING_KEXEC_IMAGE:
+   func = KEXEC_CHECK;
+   break;
+   case READING_KEXEC_INITRAMFS:
+   func = INITRAMFS_CHECK;
+   break;
+   default:
+   func = FILE_CHECK;
+   break;
+   }
 
return process_measurement(file, buf, size, MAY_READ, func, 0);
 }
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 7571ce8..d02560e 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -612,6 +612,10 @@ static int ima_parse_rule(char *rule, struct 
ima_rule_entry *entry)
entry->func = MMAP_CHECK;
else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
entry->func = BPRM_CHECK;
+   else if (strcmp(args[0].from, "KEXEC_CHECK") == 0)
+   entry->func = KEXEC_CHECK;
+   else if (strcmp(args[0].from, "INITRAMFS_CHECK") == 0)
+   entry->func = INITRAMFS_CHECK;
else
result = -EINVAL;
if (!result)
@@ -855,7 +859,8 @@ static char *mask_tokens[] = {
 
 enum {
func_file = 0, func_mmap, func_bprm,
-   func_module, fu

[PATCH v3 20/22] ima: load policy using path

2016-02-03 Thread Mimi Zohar
From: Dmitry Kasatkin <d.kasat...@samsung.com>

We currently cannot do appraisal or signature vetting of IMA policies
since we currently can only load IMA policies by writing the contents
of the policy directly in, as follows:

cat policy-file > /ima/policy

If we provide the kernel the path to the IMA policy so it can load
the policy itself it'd be able to later appraise or vet the file
signature if it has one.  This patch adds support to load the IMA
policy with a given path as follows:

echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy

Changelog v3:
- moved kernel_read_file_from_path() to a separate patch
v2:
- after re-ordering the patches, replace calling integrity_kernel_read()
  to read the file with kernel_read_file_from_path() (Mimi)
- Patch description re-written by Luis R. Rodriguez

Signed-off-by: Dmitry Kasatkin <dmitry.kasat...@huawei.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/fs.h  |  1 +
 security/integrity/ima/ima_fs.c | 43 +++--
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index d4d556e..b648e6d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2531,6 +2531,7 @@ enum kernel_read_file_id {
READING_MODULE,
READING_KEXEC_IMAGE,
READING_KEXEC_INITRAMFS,
+   READING_POLICY,
READING_MAX_ID
 };
 
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index f355231..00ccd67 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ima.h"
 
@@ -258,6 +259,41 @@ static const struct file_operations 
ima_ascii_measurements_ops = {
.release = seq_release,
 };
 
+static ssize_t ima_read_policy(char *path)
+{
+   void *data;
+   char *datap;
+   loff_t size;
+   int rc, pathlen = strlen(path);
+
+   char *p;
+
+   /* remove \n */
+   datap = path;
+   strsep(, "\n");
+
+   rc = kernel_read_file_from_path(path, , , 0, READING_POLICY);
+   if (rc < 0)
+   return rc;
+
+   datap = data;
+   while (size > 0 && (p = strsep(, "\n"))) {
+   pr_debug("rule: %s\n", p);
+   rc = ima_parse_add_rule(p);
+   if (rc < 0)
+   break;
+   size -= rc;
+   }
+
+   vfree(data);
+   if (rc < 0)
+   return rc;
+   else if (size)
+   return -EINVAL;
+   else
+   return pathlen;
+}
+
 static ssize_t ima_write_policy(struct file *file, const char __user *buf,
size_t datalen, loff_t *ppos)
 {
@@ -286,9 +322,12 @@ static ssize_t ima_write_policy(struct file *file, const 
char __user *buf,
result = mutex_lock_interruptible(_write_mutex);
if (result < 0)
goto out_free;
-   result = ima_parse_add_rule(data);
-   mutex_unlock(_write_mutex);
 
+   if (data[0] == '/')
+   result = ima_read_policy(data);
+   else
+   result = ima_parse_add_rule(data);
+   mutex_unlock(_write_mutex);
 out_free:
kfree(data);
 out:
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 22/22] ima: require signed IMA policy

2016-02-03 Thread Mimi Zohar
Require the IMA policy to be signed when additional rules can be added.

v1:
- initialize the policy flag
- include IMA_APPRAISE_POLICY in the policy flag

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_policy.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index 39a811a..ba0f6dc 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -129,6 +129,10 @@ static struct ima_rule_entry default_appraise_rules[] = {
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = 
IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = 
IMA_FSMAGIC},
+#ifdef CONFIG_IMA_WRITE_POLICY
+   {.action = APPRAISE, .func = POLICY_CHECK,
+   .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
 #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
 #else
@@ -412,9 +416,12 @@ void __init ima_init_policy(void)
for (i = 0; i < appraise_entries; i++) {
list_add_tail(_appraise_rules[i].list,
  _default_rules);
+   if (default_appraise_rules[i].func == POLICY_CHECK)
+   temp_ima_appraise |= IMA_APPRAISE_POLICY;
}
 
ima_rules = _default_rules;
+   ima_update_policy_flag();
 }
 
 /* Make sure we have a valid policy, at least containing some rules. */
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 03/22] ima: use "ima_hooks" enum as function argument

2016-02-03 Thread Mimi Zohar
Cleanup the function arguments by using "ima_hooks" enumerator as needed.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h  | 25 +
 security/integrity/ima/ima_api.c  |  6 +++---
 security/integrity/ima/ima_appraise.c | 13 +++--
 security/integrity/ima/ima_main.c | 14 +++---
 security/integrity/ima/ima_policy.c   |  6 +++---
 5 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index fb8da36..b7e7935 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -137,9 +137,18 @@ static inline unsigned long ima_hash_key(u8 *digest)
return hash_long(*digest, IMA_HASH_BITS);
 }
 
+enum ima_hooks {
+   FILE_CHECK = 1,
+   MMAP_CHECK,
+   BPRM_CHECK,
+   MODULE_CHECK,
+   FIRMWARE_CHECK,
+   POST_SETATTR
+};
+
 /* LIM API function definitions */
-int ima_get_action(struct inode *inode, int mask, int function);
-int ima_must_measure(struct inode *inode, int mask, int function);
+int ima_get_action(struct inode *inode, int mask, enum ima_hooks func);
+int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
struct file *file, enum hash_algo algo);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file 
*file,
@@ -156,8 +165,6 @@ void ima_free_template_entry(struct ima_template_entry 
*entry);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
 /* IMA policy related functions */
-enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, 
FIRMWARE_CHECK, POST_SETATTR };
-
 int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
 int flags);
 void ima_init_policy(void);
@@ -179,21 +186,22 @@ int ima_policy_show(struct seq_file *m, void *v);
 #define IMA_APPRAISE_FIRMWARE  0x10
 
 #ifdef CONFIG_IMA_APPRAISE
-int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
+int ima_appraise_measurement(enum ima_hooks func,
+struct integrity_iint_cache *iint,
 struct file *file, const unsigned char *filename,
 struct evm_ima_xattr_data *xattr_value,
 int xattr_len, int opened);
 int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
-  int func);
+  enum ima_hooks func);
 enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
 int xattr_len);
 int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
 
 #else
-static inline int ima_appraise_measurement(int func,
+static inline int ima_appraise_measurement(enum ima_hooks func,
   struct integrity_iint_cache *iint,
   struct file *file,
   const unsigned char *filename,
@@ -215,7 +223,8 @@ static inline void ima_update_xattr(struct 
integrity_iint_cache *iint,
 }
 
 static inline enum integrity_status ima_get_cache_status(struct 
integrity_iint_cache
-*iint, int func)
+*iint,
+enum ima_hooks func)
 {
return INTEGRITY_UNKNOWN;
 }
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index e7c7a5d..8750254 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -156,7 +156,7 @@ err_out:
  * ima_get_action - appraise & measure decision based on policy.
  * @inode: pointer to inode to measure
  * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
- * @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, 
MODULE_CHECK)
+ * @func: caller identifier
  *
  * The policy is defined in terms of keypairs:
  * subj=, obj=, type=, func=, mask=, fsmagic=
@@ -168,13 +168,13 @@ err_out:
  * Returns IMA_MEASURE, IMA_APPRAISE mask.
  *
  */
-int ima_get_action(struct inode *inode, int mask, int function)
+int ima_get_action(struct inode *inode, int mask, enum ima_hooks func)
 {
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
 
flags &= ima_policy_flag;
 
-   return ima_match_policy(inode, function, mask, flags);
+   return ima_match_policy(inode, func, mask, flags);
 }
 
 /*
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 9c2b46b..28884

[PATCH v3 13/22] firmware: replace call to fw_read_file_contents() with kernel version

2016-02-03 Thread Mimi Zohar
Replace the fw_read_file_contents with kernel_file_read_from_path().

Although none of the upstreamed LSMs define a kernel_fw_from_file hook,
IMA is called by the security function to prevent unsigned firmware from
being loaded and to measure/appraise signed firmware, based on policy.

Instead of reading the firmware twice, once for measuring/appraising the
firmware and again for reading the firmware contents into memory, the
kernel_post_read_file() security hook calculates the file hash based on
the in memory file buffer.  The firmware is read once.

This patch removes the LSM kernel_fw_from_file() hook and security call.

Changelog v3:
- remove kernel_fw_from_file hook
- use kernel_file_read_from_path() - requested by Luis
v2:
- reordered and squashed firmware patches
- fix MAX firmware size (Kees Cook)

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 drivers/base/firmware_class.c | 48 +++
 include/linux/fs.h|  1 +
 include/linux/ima.h   |  6 -
 include/linux/lsm_hooks.h | 11 -
 include/linux/security.h  |  7 --
 security/integrity/ima/ima_main.c | 21 -
 security/security.c   | 13 ---
 7 files changed, 19 insertions(+), 88 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index c658cec..e06a3d8 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -291,37 +291,6 @@ static const char * const fw_path[] = {
 module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
 MODULE_PARM_DESC(path, "customized firmware image search path with a higher 
priority than default path");
 
-static int fw_read_file_contents(struct file *file, struct firmware_buf 
*fw_buf)
-{
-   int size;
-   char *buf;
-   int rc;
-
-   if (!S_ISREG(file_inode(file)->i_mode))
-   return -EINVAL;
-   size = i_size_read(file_inode(file));
-   if (size <= 0)
-   return -EINVAL;
-   buf = vmalloc(size);
-   if (!buf)
-   return -ENOMEM;
-   rc = kernel_read(file, 0, buf, size);
-   if (rc != size) {
-   if (rc > 0)
-   rc = -EIO;
-   goto fail;
-   }
-   rc = security_kernel_fw_from_file(file, buf, size);
-   if (rc)
-   goto fail;
-   fw_buf->data = buf;
-   fw_buf->size = size;
-   return 0;
-fail:
-   vfree(buf);
-   return rc;
-}
-
 static void fw_finish_direct_load(struct device *device,
  struct firmware_buf *buf)
 {
@@ -334,6 +303,7 @@ static void fw_finish_direct_load(struct device *device,
 static int fw_get_filesystem_firmware(struct device *device,
   struct firmware_buf *buf)
 {
+   loff_t size;
int i, len;
int rc = -ENOENT;
char *path;
@@ -343,8 +313,6 @@ static int fw_get_filesystem_firmware(struct device *device,
return -ENOMEM;
 
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-   struct file *file;
-
/* skip the unset customized path */
if (!fw_path[i][0])
continue;
@@ -356,12 +324,11 @@ static int fw_get_filesystem_firmware(struct device 
*device,
break;
}
 
-   file = filp_open(path, O_RDONLY, 0);
-   if (IS_ERR(file))
-   continue;
-   rc = fw_read_file_contents(file, buf);
-   fput(file);
+   buf->size = 0;
+   rc = kernel_read_file_from_path(path, >data, ,
+   INT_MAX, READING_FIRMWARE);
if (rc == 0) {
+   buf->size = (size_t) size;
dev_dbg(device, "direct-loading %s\n",
buf->fw_id);
fw_finish_direct_load(device, buf);
@@ -689,8 +656,9 @@ static ssize_t firmware_loading_store(struct device *dev,
dev_err(dev, "%s: map pages failed\n",
__func__);
else
-   rc = security_kernel_fw_from_file(NULL,
-   fw_buf->data, fw_buf->size);
+   rc = security_kernel_post_read_file(NULL,
+   fw_buf->data, fw_buf->size,
+   READING_FIRMWARE);
 
/*
 * Same logic as fw_load_abort, only the DONE bit
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 962c491..2a9670a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2527,6 +2527,7 @@ static inline void i_rea

[PATCH v3 02/22] ima: refactor ima_policy_show() to display "ima_hooks" rules

2016-02-03 Thread Mimi Zohar
Define and call a function to display the "ima_hooks" rules.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_policy.c | 63 +
 1 file changed, 36 insertions(+), 27 deletions(-)

diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index e0e18cc..43b6425 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -903,6 +903,40 @@ void ima_policy_stop(struct seq_file *m, void *v)
 #define mt(token)  mask_tokens[token]
 #define ft(token)  func_tokens[token]
 
+/*
+ * policy_func_show - display the ima_hooks policy rule
+ */
+static void policy_func_show(struct seq_file *m, enum ima_hooks func)
+{
+   char tbuf[64] = {0,};
+
+   switch (func) {
+   case FILE_CHECK:
+   seq_printf(m, pt(Opt_func), ft(func_file));
+   break;
+   case MMAP_CHECK:
+   seq_printf(m, pt(Opt_func), ft(func_mmap));
+   break;
+   case BPRM_CHECK:
+   seq_printf(m, pt(Opt_func), ft(func_bprm));
+   break;
+   case MODULE_CHECK:
+   seq_printf(m, pt(Opt_func), ft(func_module));
+   break;
+   case FIRMWARE_CHECK:
+   seq_printf(m, pt(Opt_func), ft(func_firmware));
+   break;
+   case POST_SETATTR:
+   seq_printf(m, pt(Opt_func), ft(func_post));
+   break;
+   default:
+   snprintf(tbuf, sizeof(tbuf), "%d", func);
+   seq_printf(m, pt(Opt_func), tbuf);
+   break;
+   }
+   seq_puts(m, " ");
+}
+
 int ima_policy_show(struct seq_file *m, void *v)
 {
struct ima_rule_entry *entry = v;
@@ -924,33 +958,8 @@ int ima_policy_show(struct seq_file *m, void *v)
 
seq_puts(m, " ");
 
-   if (entry->flags & IMA_FUNC) {
-   switch (entry->func) {
-   case FILE_CHECK:
-   seq_printf(m, pt(Opt_func), ft(func_file));
-   break;
-   case MMAP_CHECK:
-   seq_printf(m, pt(Opt_func), ft(func_mmap));
-   break;
-   case BPRM_CHECK:
-   seq_printf(m, pt(Opt_func), ft(func_bprm));
-   break;
-   case MODULE_CHECK:
-   seq_printf(m, pt(Opt_func), ft(func_module));
-   break;
-   case FIRMWARE_CHECK:
-   seq_printf(m, pt(Opt_func), ft(func_firmware));
-   break;
-   case POST_SETATTR:
-   seq_printf(m, pt(Opt_func), ft(func_post));
-   break;
-   default:
-   snprintf(tbuf, sizeof(tbuf), "%d", entry->func);
-   seq_printf(m, pt(Opt_func), tbuf);
-   break;
-   }
-   seq_puts(m, " ");
-   }
+   if (entry->flags & IMA_FUNC)
+   policy_func_show(m, entry->func);
 
if (entry->flags & IMA_MASK) {
if (entry->mask & MAY_EXEC)
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 17/22] ima: remove firmware and module specific cached status info

2016-02-03 Thread Mimi Zohar
Each time a file is read by the kernel, the file should be re-measured and
the file signature re-appraised, based on policy.  As there is no need to
preserve the status information, this patch replaces the firmware and
module specific cache status with a generic one named read_file.

This change simplifies adding support for other files read by the kernel.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/iint.c |  4 ++--
 security/integrity/ima/ima.h  |  3 ++-
 security/integrity/ima/ima_appraise.c | 35 ---
 security/integrity/ima/ima_policy.c   |  9 -
 security/integrity/integrity.h| 16 
 5 files changed, 28 insertions(+), 39 deletions(-)

diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 8f1ab37..345b759 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -77,7 +77,7 @@ static void iint_free(struct integrity_iint_cache *iint)
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
-   iint->ima_module_status = INTEGRITY_UNKNOWN;
+   iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
kmem_cache_free(iint_cache, iint);
 }
@@ -157,7 +157,7 @@ static void init_once(void *foo)
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
-   iint->ima_module_status = INTEGRITY_UNKNOWN;
+   iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
 }
 
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 0b7134c..a5d2592 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -144,9 +144,10 @@ enum ima_hooks {
FILE_CHECK = 1,
MMAP_CHECK,
BPRM_CHECK,
+   POST_SETATTR,
MODULE_CHECK,
FIRMWARE_CHECK,
-   POST_SETATTR
+   MAX_CHECK
 };
 
 /* LIM API function definitions */
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index cb0d0ff..6b4694a 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -74,13 +74,12 @@ enum integrity_status ima_get_cache_status(struct 
integrity_iint_cache *iint,
return iint->ima_mmap_status;
case BPRM_CHECK:
return iint->ima_bprm_status;
-   case MODULE_CHECK:
-   return iint->ima_module_status;
-   case FIRMWARE_CHECK:
-   return iint->ima_firmware_status;
case FILE_CHECK:
-   default:
+   case POST_SETATTR:
return iint->ima_file_status;
+   case MODULE_CHECK ... MAX_CHECK - 1:
+   default:
+   return iint->ima_read_status;
}
 }
 
@@ -95,15 +94,14 @@ static void ima_set_cache_status(struct 
integrity_iint_cache *iint,
case BPRM_CHECK:
iint->ima_bprm_status = status;
break;
-   case MODULE_CHECK:
-   iint->ima_module_status = status;
-   break;
-   case FIRMWARE_CHECK:
-   iint->ima_firmware_status = status;
-   break;
case FILE_CHECK:
-   default:
+   case POST_SETATTR:
iint->ima_file_status = status;
+   break;
+   case MODULE_CHECK ... MAX_CHECK - 1:
+   default:
+   iint->ima_read_status = status;
+   break;
}
 }
 
@@ -117,15 +115,14 @@ static void ima_cache_flags(struct integrity_iint_cache 
*iint,
case BPRM_CHECK:
iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED);
break;
-   case MODULE_CHECK:
-   iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED);
-   break;
-   case FIRMWARE_CHECK:
-   iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED);
-   break;
case FILE_CHECK:
-   default:
+   case POST_SETATTR:
iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED);
+   break;
+   case MODULE_CHECK ... MAX_CHECK - 1:
+   default:
+   iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED);
+   break;
}
 }
 
diff --git a/security/integrity/ima/ima_policy.c 
b/security/integrity/ima/ima_policy.c
index cfbe86f..7571ce8 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -300,13 +300,12 @@ static int get_subaction(struct ima_rule_entry *rule, 
enum ima_hooks func)
return IMA_MMAP_APPRAISE;
case BPRM_CHECK:
return IMA_BPRM_APPRAISE;
-   case MODULE_CHECK:
-   return IMA_MODULE_APPRAISE;
-   

[PATCH v3 10/22] ima: calculate the hash of a buffer using aynchronous hash(ahash)

2016-02-03 Thread Mimi Zohar
Setting up ahash has some overhead.  Only use ahash to calculate the
hash of a buffer, if the buffer is larger than ima_ahash_minsize.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_crypto.c | 75 -
 1 file changed, 73 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index fccb6ce..38f2ed8 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -519,6 +519,63 @@ int ima_calc_field_array_hash(struct ima_field_data 
*field_data,
return rc;
 }
 
+static int calc_buffer_ahash_atfm(const void *buf, loff_t len,
+ struct ima_digest_data *hash,
+ struct crypto_ahash *tfm)
+{
+   struct ahash_request *req;
+   struct scatterlist sg;
+   struct ahash_completion res;
+   int rc, ahash_rc = 0;
+
+   hash->length = crypto_ahash_digestsize(tfm);
+
+   req = ahash_request_alloc(tfm, GFP_KERNEL);
+   if (!req)
+   return -ENOMEM;
+
+   init_completion();
+   ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+  CRYPTO_TFM_REQ_MAY_SLEEP,
+  ahash_complete, );
+
+   rc = ahash_wait(crypto_ahash_init(req), );
+   if (rc)
+   goto out;
+
+   sg_init_one(, buf, len);
+   ahash_request_set_crypt(req, , NULL, len);
+
+   ahash_rc = crypto_ahash_update(req);
+
+   /* wait for the update request to complete */
+   rc = ahash_wait(ahash_rc, );
+   if (!rc) {
+   ahash_request_set_crypt(req, NULL, hash->digest, 0);
+   rc = ahash_wait(crypto_ahash_final(req), );
+   }
+out:
+   ahash_request_free(req);
+   return rc;
+}
+
+static int calc_buffer_ahash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   struct crypto_ahash *tfm;
+   int rc;
+
+   tfm = ima_alloc_atfm(hash->algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   rc = calc_buffer_ahash_atfm(buf, len, hash, tfm);
+
+   ima_free_atfm(tfm);
+
+   return rc;
+}
+
 static int calc_buffer_shash_tfm(const void *buf, loff_t size,
struct ima_digest_data *hash,
struct crypto_shash *tfm)
@@ -550,8 +607,8 @@ static int calc_buffer_shash_tfm(const void *buf, loff_t 
size,
return rc;
 }
 
-int ima_calc_buffer_hash(const void *buf, loff_t len,
-struct ima_digest_data *hash)
+static int calc_buffer_shash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
 {
struct crypto_shash *tfm;
int rc;
@@ -566,6 +623,20 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,
return rc;
 }
 
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   int rc;
+
+   if (ima_ahash_minsize && len >= ima_ahash_minsize) {
+   rc = calc_buffer_ahash(buf, len, hash);
+   if (!rc)
+   return 0;
+   }
+
+   return calc_buffer_shash(buf, len, hash);
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
if (!ima_used_chip)
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[PATCH v3 11/22] ima: define a new hook to measure and appraise a file already in memory

2016-02-03 Thread Mimi Zohar
This patch defines a new IMA hook ima_post_read_file() for measuring
and appraising files read by the kernel. The caller loads the file into
memory before calling this function, which calculates the hash followed by
the normal IMA policy based processing.

Changelog v3:
- rename ima_hash_and_process_file() to ima_post_read_file()

v1:
- To simplify patch review, separate the IMA changes from the kexec
and initramfs changes in "ima: measure and appraise kexec image and
initramfs" patch.  This patch contains just the IMA changes.  The
kexec and initramfs changes are with the rest of the kexec changes
in "kexec: replace call to copy_file_from_fd() with kernel version".

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 include/linux/ima.h   |  8 +++
 include/linux/security.h  |  1 +
 security/integrity/ima/ima.h  |  4 +++-
 security/integrity/ima/ima_api.c  |  6 +++--
 security/integrity/ima/ima_appraise.c |  2 +-
 security/integrity/ima/ima_main.c | 45 ---
 security/integrity/ima/ima_policy.c   |  1 +
 security/integrity/integrity.h|  7 --
 security/security.c   |  7 +-
 9 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 120ccc5..d29a6a2 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -20,6 +20,8 @@ extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern int ima_module_check(struct file *file);
 extern int ima_fw_from_file(struct file *file, char *buf, size_t size);
+extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
+ enum kernel_read_file_id id);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -52,6 +54,12 @@ static inline int ima_fw_from_file(struct file *file, char 
*buf, size_t size)
return 0;
 }
 
+static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
+enum kernel_read_file_id id)
+{
+   return 0;
+}
+
 #endif /* CONFIG_IMA */
 
 #ifdef CONFIG_IMA_APPRAISE
diff --git a/include/linux/security.h b/include/linux/security.h
index b68ce94..d920718 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -24,6 +24,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 2c5262f..0b7134c 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -19,6 +19,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -152,7 +153,8 @@ enum ima_hooks {
 int ima_get_action(struct inode *inode, int mask, enum ima_hooks func);
 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file, enum hash_algo algo);
+   struct file *file, void *buf, loff_t size,
+   enum hash_algo algo);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file 
*file,
   const unsigned char *filename,
   struct evm_ima_xattr_data *xattr_value,
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 8750254..370e42d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -188,7 +188,8 @@ int ima_get_action(struct inode *inode, int mask, enum 
ima_hooks func)
  * Return 0 on success, error code otherwise
  */
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file, enum hash_algo algo)
+   struct file *file, void *buf, loff_t size,
+   enum hash_algo algo)
 {
const char *audit_cause = "failed";
struct inode *inode = file_inode(file);
@@ -210,7 +211,8 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
 
hash.hdr.algo = algo;
 
-   result = ima_calc_file_hash(file, );
+   result = (!buf) ?  ima_calc_file_hash(file, ) :
+   ima_calc_buffer_hash(buf, size, );
if (!result) {
int length = sizeof(hash.hdr) + hash.hdr.length;
void *tmpbuf = krealloc(iint->ima_hash, length,
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 2888449..cb0d0ff 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -300,7 +300,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, 
struct file *file)
if (iint->flags & IMA_DIGSIG)
return;
 
-   rc = ima_collect_measurement(iint, file, ima_hash_algo);
+   rc

Re: [RFC PATCH v2 06/11] kexec: replace call to copy_file_from_fd() with kernel version

2016-01-26 Thread Mimi Zohar
Hi Dave,

On Tue, 2016-01-26 at 09:20 +0800, Dave Young wrote:
> Hi, Mimi
> 
> On 01/25/16 at 10:04am, Mimi Zohar wrote:
> > On Mon, 2016-01-25 at 14:37 +0800, Dave Young wrote:
> > > Hi, Mimi
> > > 
> > > Besides of code issues, I have several thing to be understand:
> > > 
> > > What is the effect to kexec behavior with this patchset?
> > >   - without IMA enabled (kconfig or kernel cmdline) it will be same as 
> > > before?
> > 
> > Yes, without IMA configured or an IMA policy, it is the same as before.
> > 
> > >   - with IMA enabled for kernel bzImage, kexec_file_load will check both 
> > > ima
> > > signature and original pe file signature, those two mechanisms are
> > > somehow duplicated. I'm not sure if we need both for bzImage.
> > 
> > IMA provides a uniform method of measuring and appraising all files on
> > the system, based on policy.  The IMA policy could prevent the original
> > kexec syscall.  On systems without MODULE_SIG_FORCE, the IMA policy
> > would require an IMA signature as well.  (The current patch would
> > require both, even when MODULE_SIG_FORCE is enabled.)
> 
> Hmm, enabling policy is in userspace (initramfs?) so it may not be good
> enough for secure boot case. IMA can be used as a uniform method for kexec
> kernel signature verification for !UEFI or !secure-boot case. 

Normally, the kernel is booted with a builtin policy.   The policy, if
it is being replaced, is normally replaced in the initramfs.  This patch
set introduces the concept of a signed policy.   Refer to the last 3
patches. 

> > 
> > The pe format is supported on x86.  Why require the pe file signature
> > format on all platforms?
> 
> For secure boot purpose, an uefi bootable kernel (as an uefi applicatioin)
> require it to be a pe file.
> 
> But for !secure-boot it is not mandatory.

It would be more appropriate to say that "UEFI secure boot" requires a
pe file, as opposed to "secure boot" in general.

> > > Do you have a simple usage documentation about how to test it?
> > 
> > The wiki[1] and ima-evm-ctl package[2] have directions for enabling
> > IMA/IMA-appraisal.
> > 
> > To include just the kexec image and initramfs file hashes in the IMA
> > measurement list, create a file containing the following IMA policy
> > rules.  "cat" the policy and redirect the output
> > to /sys/kernel/security/ima/policy.   After loading the kexec image and
> > initramfs, the IMA measurements will be included in the measurement list
> > (/sys/kernel/security/ima/ascii_runtime_measurements)
> > 
> > IMA policy: 
> > measure func=KEXEC_CHECK
> > measure func=INITRAMFS_CHECK
> > 
> > Appraising the kexec image and initramfs is a bit more complicated as it
> > requires creating a key, which is signed by a key on the system keyring,
> > and loading the key onto the trusted IMA keyring.  To simplify testing,
> > without CONFIG_IMA_TRUSTED_KEYRING enabled, the key being loaded onto
> > the IMA keyring does not need to be signed.  The evmctl man page[2]
> > contains directions for creating and loading the key onto the IMA
> > keyring. 
> > 
> > To appraise just the kexec image and initramfs files, add the following
> > two rules to the IMA policy and load the policy as before.  (The policy
> > can only be loaded once per boot, unless IMA_WRITE_POLICY is configured.
> > With the default appraisal policy, the policy would need to signed.)
> > Sign the kexec image and initramfs with evmctl before loading them.
> > 
> > # evmctl ima_sign -k  -a sha256 
> > # evmctl ima_sign -k  -a sha256 
> > 
> > IMA appraise policy:
> > appraise func=KEXEC_CHECK appraise_type=imasig
> > appraise func=INITRAMFS_CHECK appraise_type=imasig
> > 
> > [1] http://sourceforge.net/p/linux-ima/wiki/Home
> > [2] http://linux-ima.sourceforge.net/evmctl.1.html
> 
> Thank you, will try
> 
> > 
> > > > +{
> > > > +   struct fd f = fdget(fd);
> > > > +   int ret = -ENOEXEC;
> > > 
> > > -EBADF looks better?
> > 
> > Sure.
> > 
> Seems you missed another comment about the policy id name?
> can the name be like below?
> KEXEC_KERNEL_CHECK
> KEXEC_INITRAMFS_CHECK

Luis suggested making the enumeration more generic, not IMA specific.  I
suggested the following:

enum kernel_read_file_id {
READING_KEXEC_IMAGE = 1,
READING_KEXEC_INITRAMFS,
READING_FIRMWARE,
READING_MODULE,
READING_POLICY,
READING_MAX_ID
};

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 06/11] kexec: replace call to copy_file_from_fd() with kernel version

2016-01-25 Thread Mimi Zohar
On Mon, 2016-01-25 at 14:37 +0800, Dave Young wrote:
> Hi, Mimi
> 
> Besides of code issues, I have several thing to be understand:
> 
> What is the effect to kexec behavior with this patchset?
>   - without IMA enabled (kconfig or kernel cmdline) it will be same as before?

Yes, without IMA configured or an IMA policy, it is the same as before.

>   - with IMA enabled for kernel bzImage, kexec_file_load will check both ima
> signature and original pe file signature, those two mechanisms are
> somehow duplicated. I'm not sure if we need both for bzImage.

IMA provides a uniform method of measuring and appraising all files on
the system, based on policy.  The IMA policy could prevent the original
kexec syscall.  On systems without MODULE_SIG_FORCE, the IMA policy
would require an IMA signature as well.  (The current patch would
require both, even when MODULE_SIG_FORCE is enabled.)

The pe format is supported on x86.  Why require the pe file signature
format on all platforms?

> Do you have a simple usage documentation about how to test it?

The wiki[1] and ima-evm-ctl package[2] have directions for enabling
IMA/IMA-appraisal.

To include just the kexec image and initramfs file hashes in the IMA
measurement list, create a file containing the following IMA policy
rules.  "cat" the policy and redirect the output
to /sys/kernel/security/ima/policy.   After loading the kexec image and
initramfs, the IMA measurements will be included in the measurement list
(/sys/kernel/security/ima/ascii_runtime_measurements)

IMA policy: 
measure func=KEXEC_CHECK
measure func=INITRAMFS_CHECK

Appraising the kexec image and initramfs is a bit more complicated as it
requires creating a key, which is signed by a key on the system keyring,
and loading the key onto the trusted IMA keyring.  To simplify testing,
without CONFIG_IMA_TRUSTED_KEYRING enabled, the key being loaded onto
the IMA keyring does not need to be signed.  The evmctl man page[2]
contains directions for creating and loading the key onto the IMA
keyring. 

To appraise just the kexec image and initramfs files, add the following
two rules to the IMA policy and load the policy as before.  (The policy
can only be loaded once per boot, unless IMA_WRITE_POLICY is configured.
With the default appraisal policy, the policy would need to signed.)
Sign the kexec image and initramfs with evmctl before loading them.

# evmctl ima_sign -k  -a sha256 
# evmctl ima_sign -k  -a sha256 

IMA appraise policy:
appraise func=KEXEC_CHECK appraise_type=imasig
appraise func=INITRAMFS_CHECK appraise_type=imasig

[1] http://sourceforge.net/p/linux-ima/wiki/Home
[2] http://linux-ima.sourceforge.net/evmctl.1.html

> > +{
> > +   struct fd f = fdget(fd);
> > +   int ret = -ENOEXEC;
> 
> -EBADF looks better?

Sure.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 06/11] kexec: replace call to copy_file_from_fd() with kernel version

2016-01-25 Thread Mimi Zohar
On Mon, 2016-01-25 at 21:34 +0100, Luis R. Rodriguez wrote:
> On Mon, Jan 25, 2016 at 10:04:18AM -0500, Mimi Zohar wrote:
> > On Mon, 2016-01-25 at 14:37 +0800, Dave Young wrote:
> > > Hi, Mimi
> > > 
> > > Besides of code issues, I have several thing to be understand:
> > > 
> > > What is the effect to kexec behavior with this patchset?
> > >   - without IMA enabled (kconfig or kernel cmdline) it will be same as 
> > > before?
> > 
> > Yes, without IMA configured or an IMA policy, it is the same as before.
> 
> That's a bit unfair to your work here, this actually paves the way
> for not only IMA but also other LSMs to vet for the kexec/initramfs
> given LSM hooks are used now on a common kernel read set of functions.

Right, I responded to his questions about IMA and not the bigger picture.

> > 
> > >   - with IMA enabled for kernel bzImage, kexec_file_load will check both 
> > > ima
> > > signature and original pe file signature, those two mechanisms are
> > > somehow duplicated. I'm not sure if we need both for bzImage.
> > 
> > IMA provides a uniform method of measuring and appraising all files on
> > the system, based on policy.  The IMA policy could prevent the original
> > kexec syscall. 

Sorry for jumping back and forth between security hooks.  Similarly, for
the kernel module hook, it prevents the original kernel module syscall
as well.

> On systems without MODULE_SIG_FORCE, the IMA policy
> > would require an IMA signature as well.  (The current patch would
> > require both, even when MODULE_SIG_FORCE is enabled.)
> 
> 
> Right, so what this approach has revealed really is that architecturally
> MODULE_SIG_FORCE should have been an LSM but its not, its also hard to make it
> an LSM.  Now with LSM stacking this might make more sense but that requires
> work and who knows when and if that will happen. 

I kind of lost you here.  A new mini LSM would require file signatures
of an existing type or would it be a new method for verifying file
signatures?

> In the meantime we'll live
> with the fact that enabling MODULE_SIG_FORCE means you want to stack on
> top of the LSMs you have enabled, the MODULE_SIG_FORCE functionality being
> all kernel related and perhaps easier to manage / set.

As I see it, with MODULE_SIG_FORCE, IMA-appraisal could relax its own
policy knowing that only signed kernel modules are loaded.  Without
MODULE_SIG_FORCE enabled, then IMA-appraisal needs to do the enforcing,
of course based on policy.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 07/11] firmware: replace call to fw_read_file_contents() with kernel version

2016-01-21 Thread Mimi Zohar
On Wed, 2016-01-20 at 15:56 -0800, Luis R. Rodriguez wrote:
> On Wed, Jan 20, 2016 at 3:39 PM, Luis R. Rodriguez  wrote:

> >> @@ -350,13 +321,18 @@ static int fw_get_filesystem_firmware(struct device 
> >> *device,
> >>   file = filp_open(path, O_RDONLY, 0);
> >>   if (IS_ERR(file))
> >>   continue;
> >> - rc = fw_read_file_contents(file, buf);
> >> +
> >> + buf->size = 0;
> >> + rc = kernel_read_file(file, >data, , INT_MAX,
> >> +   FIRMWARE_CHECK);
> >
> > The way kernel firmware signing was implemented was that we'd first read the
> > foo.sig (or whatever extension we use). 

Was there a reason for using a detached signature and not using the same
method as kernel modules?

> The same kernel_read_file() would be
> > used if this gets applied so this would still works well with that. Of 
> > course
> > folks using IMA and their own security policy would just disable the kernel
> > fw signing facility.

Right, support for not measuring/appraising the firmware and sig would
be supported in the policy.

> >> diff --git a/include/linux/ima.h b/include/linux/ima.h
> >> index ae91938..0a7f039 100644
> >> --- a/include/linux/ima.h
> >> +++ b/include/linux/ima.h
> >> @@ -16,6 +16,7 @@ struct linux_binprm;
> >>  enum ima_policy_id {
> >>   KEXEC_CHECK = 1,
> >>   INITRAMFS_CHECK,
> >> + FIRMWARE_CHECK,
> >>   IMA_MAX_READ_CHECK
> >>  };
> >
> > The only thing that is worth questioning here in light of kernel fw signing 
> > is
> > what int policy_id do we use? Would we be OK to add FIRMWARE_SIG_CHECK later
> > While at it, perhaps kernel_read_file() last argument should be enum
> > ima_policy_id then. If the policy_id is going to be used elsewhere outside 
> > of
> > IMA then perhaps ima.h is not the best place for it ? Would fs.h for type of
> > file be OK ? Then we'd have a list of known file types the kernel reads.

I would definitely prefer the enumeration be defined at the VFS layer.
For example, 

enum kernel_read_file_id {
READING_KEXEC_IMAGE,
READING_KEXEC_INITRAMFS,
READING_FIRMWARE,
READING_FIRMWARE_SIG,
READING_MAX_ID
};

Agreed, the last field of kernel_read_file() and the wrappers should be
the enumeration. 

> Actually your patch #9 "ima: load policy using path" defines
> kernel_read_file_from_path and since the firmware code uses a path
> this code would be much cleaner if instead you used that. It'd mean
> more code sharing and would make firmware code cleaner. Could you
> re-order that to go first and then later this as its first user?
> Perhaps add the helper for the firmware patch.

Thanks, I missed that.  I'll include this change in the next version.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 07/11] firmware: replace call to fw_read_file_contents() with kernel version

2016-01-21 Thread Mimi Zohar
On Tue, 2016-01-19 at 16:10 -0800, Kees Cook wrote:
> On Mon, Jan 18, 2016 at 7:11 AM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > Replace fw_read_file_contents() for reading a file with the common VFS
> > kernel_read_file() function.  A benefit of calling kernel_read_file()
> > to read the firmware is the firmware is read only once, instead of once
> > for measuring/appraising the firmware and again for reading the file
> > contents into memory.
> >
> > This patch retains the kernel_fw_from_file() hook, which is called from
> > security_kernel_post_read_file(), but removes the
> > sercurity_kernel_fw_from_file() function.
> >
> > Changelog:
> > - reordered and squashed firmware patches
> > - fix MAX firmware size (Kees Cook)
> >
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> 
> Reviewed-by: Kees Cook <keesc...@chromium.org>

Thanks!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 03/11] ima: provide buffer hash calculation function

2016-01-21 Thread Mimi Zohar
On Tue, 2016-01-19 at 21:26 +0200, Dmitry Kasatkin wrote:
> On Mon, Jan 18, 2016 at 5:11 PM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > From: Dmitry Kasatkin <d.kasat...@samsung.com>
> >
> > This patch provides convenient buffer hash calculation function.
> >
> > Changelog:
> > - rewrite to support loff_t sized buffers - Mimi
> >   (based on Fenguang Wu's testing)
> >
> > Signed-off-by: Dmitry Kasatkin <d.kasat...@samsung.com>
> > Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> > ---
> >  security/integrity/ima/ima.h|  2 ++
> >  security/integrity/ima/ima_crypto.c | 47 
> > +
> >  2 files changed, 49 insertions(+)
> >
> > diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> > index fb8da36..de53631 100644
> > --- a/security/integrity/ima/ima.h
> > +++ b/security/integrity/ima/ima.h
> > @@ -107,6 +107,8 @@ int ima_add_template_entry(struct ima_template_entry 
> > *entry, int violation,
> >const char *op, struct inode *inode,
> >const unsigned char *filename);
> >  int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
> > +int ima_calc_buffer_hash(const void *buf, loff_t len,
> > +struct ima_digest_data *hash);
> >  int ima_calc_field_array_hash(struct ima_field_data *field_data,
> >   struct ima_template_desc *desc, int 
> > num_fields,
> >   struct ima_digest_data *hash);
> > diff --git a/security/integrity/ima/ima_crypto.c 
> > b/security/integrity/ima/ima_crypto.c
> > index fb30ce4..8d86281 100644
> > --- a/security/integrity/ima/ima_crypto.c
> > +++ b/security/integrity/ima/ima_crypto.c
> > @@ -519,6 +519,53 @@ int ima_calc_field_array_hash(struct ima_field_data 
> > *field_data,
> > return rc;
> >  }
> >
> > +static int calc_buffer_shash_tfm(const void *buf, loff_t size,
> > +   struct ima_digest_data *hash,
> > +   struct crypto_shash *tfm)
> > +{
> > +   SHASH_DESC_ON_STACK(shash, tfm);
> > +   unsigned int len;
> > +   loff_t offset = 0;
> > +   int rc;
> > +
> > +   shash->tfm = tfm;
> > +   shash->flags = 0;
> > +
> > +   hash->length = crypto_shash_digestsize(tfm);
> > +
> > +   rc = crypto_shash_init(shash);
> > +   if (rc != 0)
> > +   return rc;
> > +
> > +   len = size < PAGE_SIZE ? size : PAGE_SIZE;
> > +   while (offset < size) {
> > +   rc = crypto_shash_update(shash, buf + offset, len);
> > +   if (rc)
> > +   break;
> > +   offset += len;
> > +   }
> > +
> 
> Hello Mimi,
> 
> May be this was my earlier patch, but it seems to have a problem of
> accessing beyond end of buffer using the same len.
> When buffer always padded by zeros it is not a problem, but it is a bug.
> 
> This seems to be better version.
> 
>while (size) {
>len = size < PAGE_SIZE ? size : PAGE_SIZE;
>rc = crypto_shash_update(shash, buf, len);
>if (rc)
>break;
>buf += len;
>size -= len;
> }
> 
> Please change my sign-of to: dmitry.kasat...@huawei.com

Good catch!  I think I unfortunately introduce this bug.  Thank you for
the review!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 01/11] ima: separate 'security.ima' reading functionality from collect

2016-01-21 Thread Mimi Zohar
On Tue, 2016-01-19 at 22:00 +0200, Dmitry Kasatkin wrote:
> Hi Mimi,
> 
> Please change
> 
> Signed-off-by: Dmitry Kasatkin 

I'll make the change here and in the other patches as well.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 02/11] vfs: define a generic function to read a file from the kernel

2016-01-21 Thread Mimi Zohar
On Wed, 2016-01-20 at 02:09 +0100, Luis R. Rodriguez wrote:
> On Mon, Jan 18, 2016 at 10:11:17AM -0500, Mimi Zohar wrote:
> > diff --git a/fs/exec.c b/fs/exec.c
> > index b06623a..6d623c2 100644
> > --- a/fs/exec.c
> > +++ b/fs/exec.c
> > @@ -831,6 +832,58 @@ int kernel_read(struct file *file, loff_t offset,
> >  
> >  EXPORT_SYMBOL(kernel_read);
> >  
> > +int kernel_read_file(struct file *file, void **buf, loff_t *size,
> > +loff_t max_size)
> > +{
> > +   loff_t i_size, pos;
> > +   ssize_t bytes = 0;
> > +   int ret;
> > +
> > +   if (!S_ISREG(file_inode(file)->i_mode))
> > +   return -EINVAL;
> > +
> > +   i_size = i_size_read(file_inode(file));
> > +   if (max_size > 0 && i_size > max_size)
> > +   return -EFBIG;
> 
> loff_t is a __kernel_loff_t, which in turn is a long long, and that's
> signed. We don't catch a negative value here, for max_size, we could
> return -EINVAL if its < 0.
> 
> > +   if (i_size == 0)
> > +   return -EINVAL;
> 
> Likewise for i_size. The setter of the size will depend on how the
> code calling this routine setup the struct file passed.
> 
> So how about adding a i_size <= 0 check here as well here?
> At least fw_read_file_contents() has historically done this,
> so if this generic read is going to skip that I'd like to
> see why. We're unifying so I rather be more pedantic.
> 
> Provided this is addressed feel free to peg:
> 
> Reviewed-by: Luis R. Rodriguez <mcg...@suse.com>

Don't know how I missed that.  Thanks!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 09/11] ima: load policy using path

2016-01-21 Thread Mimi Zohar
On Thu, 2016-01-21 at 01:05 +0100, Luis R. Rodriguez wrote:
> On Mon, Jan 18, 2016 at 10:11:24AM -0500, Mimi Zohar wrote:
> > --- a/fs/exec.c
> > +++ b/fs/exec.c
> > @@ -903,6 +903,27 @@ out:
> > return ret;
> >  }
> >  
> > +int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
> > +  loff_t max_size, int policy_id)
> > +{
> > +   struct file *file;
> > +   int ret;
> > +
> > +   if (!path || !*path)
> > +   return -EINVAL;
> > +
> > +   file = filp_open(path, O_RDONLY, 0);
> > +   if (IS_ERR(file)) {
> > +   ret = PTR_ERR(file);
> > +   pr_err("Unable to open file: %s (%d)", path, ret);
> > +   return ret;
> > +   }
> > +
> > +   ret = kernel_read_file(file, buf, size, max_size, policy_id);
> > +   fput(file);
> > +   return ret;
> > +}
> > +
> 
> EXPORT_SYMBOL_GPL() needed.

Yes.  Thank you for reviewing all the patches!

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 08/11] module: replace copy_module_from_fd with kernel version

2016-01-21 Thread Mimi Zohar
On Thu, 2016-01-21 at 01:03 +0100, Luis R. Rodriguez wrote:
> On Mon, Jan 18, 2016 at 10:11:23AM -0500, Mimi Zohar wrote:
> > This patch replaces the module copy_module_from_fd() call with the VFS
> > common kernel_read_file_from_fd() function.  Instead of reading the
> > kernel module twice, once for measuring/appraising and then loading
> > the kernel module, the file is read once.
> > 
> > This patch defines a new security hook named security_kernel_read_file(),
> > which is called before reading the file.  For now, call the module
> > security hook from security_kernel_read_file until the LSMs have been
> > converted to use the kernel_read_file hook.
> > 
> > This patch retains the kernel_module_from_file hook, but removes the
> > security_kernel_module_from_file() function.
> 
> I think it would help if your cover letter and this patch described
> a bit that some LSMs either prefer to read / check / appraise files
> prior to loading and some other prefer to do that later. You could
> explain the LSM hook preferences and what they do. Then here you
> can explain how this one prefers a hook early, but acknowledge that
> the other one still exists.

Before this patch set, IMA measured/appraised/audited a file before
allowing it to be accessed, causing the file in some cases to be read
twice.   This patch set changes that.  Files are read into memory and
then measured/appraised/audited.
 
It's been a while since this hook was added.  As I recall, Kees added
the pre module hook to limit loading kernel modules to only those
filesystems that were mounted read-only.  I would have to look at each
of the LSMs to see how they're using the hooks.

> So:
> 
> kernel_read_file() {
>   ...
>   security_kernel_read_file();
>   ...
>   security_kernel_post_read_file();
>   ...
> }
> 
> > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> > index 4e6e2af..9915310 100644
> > --- a/include/linux/lsm_hooks.h
> > +++ b/include/linux/lsm_hooks.h
> > @@ -1465,6 +1471,7 @@ union security_list_options {
> > int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
> > int (*kernel_module_request)(char *kmod_name);
> > int (*kernel_module_from_file)(struct file *file);
> > +   int (*kernel_read_file)(struct file *file, int policy_id);
> > int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
> >  int policy_id);
> > int (*task_fix_setuid)(struct cred *new, const struct cred *old,
> 
> Is the goal to eventually kill the other LSM hooks and just keep the
> file one? If so where is that done in this series? It was not clear.

As mentioned in the cover letter, consolidating the LSM hooks is not
covered in this patch set.  I was under the impression that not only
were we defining a common kernel read file function, but that we were
also consolidating the pre and post security hooks as well.  By defining
the pre and post security hooks in this patch set, it permits each of
the LSMs to migrate to the new hooks independently of each other.   Lets
ask the LSM maintainers what they think.

Paul, Casey, Kees, Jon, Tetsuo does it make sense to consolidate the
module, firmware, and kexec pre and post security hooks and have just
one set of pre and post security kernel_read_file hook instead?   Does
it make sense for this patch set to define the new hooks to allow the
LSMs to migrate to it independently of each other?

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 00/11] vfss: support for a common kernel file loader

2016-01-21 Thread Mimi Zohar
On Thu, 2016-01-21 at 21:16 +0100, Luis R. Rodriguez wrote:
> On Mon, Jan 18, 2016 at 10:11:15AM -0500, Mimi Zohar wrote:
> >
> > The latest version of these patches can be found in the next-kernel-read-v2
> > branch of:
> > git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
> > 
> > [1] Taken from Luis Rodriguez's wiki -
> > http://kernelnewbies.org/KernelProjects/common-kernel-loader
> 
> Did 0-day bot get a chance to test this tree? If not can it
> be added ?

Yes, I get the notifications.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 08/11] module: replace copy_module_from_fd with kernel version

2016-01-21 Thread Mimi Zohar
On Thu, 2016-01-21 at 08:56 -0800, Luis R. Rodriguez wrote:
> On Thu, Jan 21, 2016 at 5:12 AM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > On Thu, 2016-01-21 at 01:03 +0100, Luis R. Rodriguez wrote:
> >> On Mon, Jan 18, 2016 at 10:11:23AM -0500, Mimi Zohar wrote:
> >> > This patch replaces the module copy_module_from_fd() call with the VFS
> >> > common kernel_read_file_from_fd() function.  Instead of reading the
> >> > kernel module twice, once for measuring/appraising and then loading
> >> > the kernel module, the file is read once.
> >> >
> >> > This patch defines a new security hook named security_kernel_read_file(),
> >> > which is called before reading the file.  For now, call the module
> >> > security hook from security_kernel_read_file until the LSMs have been
> >> > converted to use the kernel_read_file hook.
> >> >
> >> > This patch retains the kernel_module_from_file hook, but removes the
> >> > security_kernel_module_from_file() function.
> >>
> >> I think it would help if your cover letter and this patch described
> >> a bit that some LSMs either prefer to read / check / appraise files
> >> prior to loading and some other prefer to do that later. You could
> >> explain the LSM hook preferences and what they do. Then here you
> >> can explain how this one prefers a hook early, but acknowledge that
> >> the other one still exists.
> >
> > Before this patch set, IMA measured/appraised/audited a file before
> > allowing it to be accessed, causing the file in some cases to be read
> > twice.   This patch set changes that.  Files are read into memory and
> > then measured/appraised/audited.
> 
> Sounds like this could help also with performance, has any preliminary
> benchmarking been done to see the effect ?

In general, IMA's pre-reading a file has negligible performance impact,
if any.   Dmitry's LinuxCon 2013 Europe talk "Integrity Protection
Solutions in Linux" had some performance statistics.  I'm not sure this
change will have much of a performance impact.

> > By defining
> > the pre and post security hooks in this patch set, it permits each of
> > the LSMs to migrate to the new hooks independently of each other.   Lets
> > ask the LSM maintainers what they think.
> 
> I see -- yeah making this a 2 step thing makes sense, so long as the
> maintainers can later expect / understand what would be done in a
> second patch set. Breaking this down in two patch sets makes sense. 

I'll defer adding the pre and post security hooks to the subsequent
patch set.

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


Re: [RFC PATCH v2 08/11] module: replace copy_module_from_fd with kernel version

2016-01-21 Thread Mimi Zohar
On Thu, 2016-01-21 at 10:45 -0500, Paul Moore wrote:
> On Thursday, January 21, 2016 08:12:12 AM Mimi Zohar wrote:
> > Paul, Casey, Kees, Jon, Tetsuo does it make sense to consolidate the
> > module, firmware, and kexec pre and post security hooks and have just
> > one set of pre and post security kernel_read_file hook instead?   Does
> > it make sense for this patch set to define the new hooks to allow the
> > LSMs to migrate to it independently of each other?
> 
> Well, as usual, the easiest way to both get solid feedback and actually get a 
> change accepted is to post patches to the affected LSMs.  Probably not what 
> you wanted to hear, but at least I'm honest :)

Unless I'm misreading the code, it might be a lot simpler than I
thought.  Of the three LSM hooks kernel_module_request,
kernel_module_from_file, and kernel_fw_from_file, the only upstreamed
LSM on any of these hooks is SELinux, which is only on the
kernel_module_request hook.

After converting the SELinux kernel_module_request hook to use the new
kernel_read_file(),  do I then remove the three hooks?   Are we
concerned about "minor" LSMs that have not been upstreamed that might be
using these hooks?

Mimi


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[RFC PATCH v2 03/11] ima: provide buffer hash calculation function

2016-01-18 Thread Mimi Zohar
From: Dmitry Kasatkin <d.kasat...@samsung.com>

This patch provides convenient buffer hash calculation function.

Changelog:
- rewrite to support loff_t sized buffers - Mimi
  (based on Fenguang Wu's testing)

Signed-off-by: Dmitry Kasatkin <d.kasat...@samsung.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h|  2 ++
 security/integrity/ima/ima_crypto.c | 47 +
 2 files changed, 49 insertions(+)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index fb8da36..de53631 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -107,6 +107,8 @@ int ima_add_template_entry(struct ima_template_entry 
*entry, int violation,
   const char *op, struct inode *inode,
   const unsigned char *filename);
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash);
 int ima_calc_field_array_hash(struct ima_field_data *field_data,
  struct ima_template_desc *desc, int num_fields,
  struct ima_digest_data *hash);
diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index fb30ce4..8d86281 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -519,6 +519,53 @@ int ima_calc_field_array_hash(struct ima_field_data 
*field_data,
return rc;
 }
 
+static int calc_buffer_shash_tfm(const void *buf, loff_t size,
+   struct ima_digest_data *hash,
+   struct crypto_shash *tfm)
+{
+   SHASH_DESC_ON_STACK(shash, tfm);
+   unsigned int len;
+   loff_t offset = 0;
+   int rc;
+
+   shash->tfm = tfm;
+   shash->flags = 0;
+
+   hash->length = crypto_shash_digestsize(tfm);
+
+   rc = crypto_shash_init(shash);
+   if (rc != 0)
+   return rc;
+
+   len = size < PAGE_SIZE ? size : PAGE_SIZE;
+   while (offset < size) {
+   rc = crypto_shash_update(shash, buf + offset, len);
+   if (rc)
+   break;
+   offset += len;
+   }
+
+   if (!rc)
+   rc = crypto_shash_final(shash, hash->digest);
+   return rc;
+}
+
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   struct crypto_shash *tfm;
+   int rc;
+
+   tfm = ima_alloc_tfm(hash->algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   rc = calc_buffer_shash_tfm(buf, len, hash, tfm);
+
+   ima_free_tfm(tfm);
+   return rc;
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
if (!ima_used_chip)
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[RFC PATCH v2 04/11] ima: calculate the hash of a buffer using aynchronous hash(ahash)

2016-01-18 Thread Mimi Zohar
Setting up ahash has some overhead.  Only use ahash to calculate the
hash of a buffer, if the buffer is larger than ima_ahash_minsize.

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima_crypto.c | 75 -
 1 file changed, 73 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index 8d86281..82c4d3c 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -519,6 +519,63 @@ int ima_calc_field_array_hash(struct ima_field_data 
*field_data,
return rc;
 }
 
+static int calc_buffer_ahash_atfm(const void *buf, loff_t len,
+ struct ima_digest_data *hash,
+ struct crypto_ahash *tfm)
+{
+   struct ahash_request *req;
+   struct scatterlist sg;
+   struct ahash_completion res;
+   int rc, ahash_rc = 0;
+
+   hash->length = crypto_ahash_digestsize(tfm);
+
+   req = ahash_request_alloc(tfm, GFP_KERNEL);
+   if (!req)
+   return -ENOMEM;
+
+   init_completion();
+   ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+  CRYPTO_TFM_REQ_MAY_SLEEP,
+  ahash_complete, );
+
+   rc = ahash_wait(crypto_ahash_init(req), );
+   if (rc)
+   goto out;
+
+   sg_init_one(, buf, len);
+   ahash_request_set_crypt(req, , NULL, len);
+
+   ahash_rc = crypto_ahash_update(req);
+
+   /* wait for the update request to complete */
+   rc = ahash_wait(ahash_rc, );
+   if (!rc) {
+   ahash_request_set_crypt(req, NULL, hash->digest, 0);
+   rc = ahash_wait(crypto_ahash_final(req), );
+   }
+out:
+   ahash_request_free(req);
+   return rc;
+}
+
+static int calc_buffer_ahash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   struct crypto_ahash *tfm;
+   int rc;
+
+   tfm = ima_alloc_atfm(hash->algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   rc = calc_buffer_ahash_atfm(buf, len, hash, tfm);
+
+   ima_free_atfm(tfm);
+
+   return rc;
+}
+
 static int calc_buffer_shash_tfm(const void *buf, loff_t size,
struct ima_digest_data *hash,
struct crypto_shash *tfm)
@@ -550,8 +607,8 @@ static int calc_buffer_shash_tfm(const void *buf, loff_t 
size,
return rc;
 }
 
-int ima_calc_buffer_hash(const void *buf, loff_t len,
-struct ima_digest_data *hash)
+static int calc_buffer_shash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
 {
struct crypto_shash *tfm;
int rc;
@@ -566,6 +623,20 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,
return rc;
 }
 
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+struct ima_digest_data *hash)
+{
+   int rc;
+
+   if (ima_ahash_minsize && len >= ima_ahash_minsize) {
+   rc = calc_buffer_ahash(buf, len, hash);
+   if (!rc)
+   return 0;
+   }
+
+   return calc_buffer_shash(buf, len, hash);
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
if (!ima_used_chip)
-- 
2.1.0


___
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec


[RFC PATCH v2 01/11] ima: separate 'security.ima' reading functionality from collect

2016-01-18 Thread Mimi Zohar
From: Dmitry Kasatkin <d.kasat...@samsung.com>

Instead of passing pointers to pointers to ima_collect_measurent() to
read and return the 'security.ima' xattr value, this patch moves the
functionality to the calling process_measurement() to directly read
the xattr and pass only the hash algo to the ima_collect_measurement().

Signed-off-by: Dmitry Kasatkin <d.kasat...@samsung.com>
Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h  | 15 +++
 security/integrity/ima/ima_api.c  | 15 +++
 security/integrity/ima/ima_appraise.c | 25 ++---
 security/integrity/ima/ima_crypto.c   |  2 +-
 security/integrity/ima/ima_init.c |  2 +-
 security/integrity/ima/ima_main.c | 11 +++
 security/integrity/ima/ima_template.c |  2 --
 security/integrity/ima/ima_template_lib.c |  1 -
 8 files changed, 33 insertions(+), 40 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 585af61..fb8da36 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "../integrity.h"
 
@@ -140,9 +141,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
 int ima_get_action(struct inode *inode, int mask, int function);
 int ima_must_measure(struct inode *inode, int mask, int function);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file,
-   struct evm_ima_xattr_data **xattr_value,
-   int *xattr_len);
+   struct file *file, enum hash_algo algo);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file 
*file,
   const unsigned char *filename,
   struct evm_ima_xattr_data *xattr_value,
@@ -188,8 +187,8 @@ int ima_must_appraise(struct inode *inode, int mask, enum 
ima_hooks func);
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
   int func);
-void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
-  struct ima_digest_data *hash);
+enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+int xattr_len);
 int ima_read_xattr(struct dentry *dentry,
   struct evm_ima_xattr_data **xattr_value);
 
@@ -221,10 +220,10 @@ static inline enum integrity_status 
ima_get_cache_status(struct integrity_iint_c
return INTEGRITY_UNKNOWN;
 }
 
-static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
-int xattr_len,
-struct ima_digest_data *hash)
+static inline enum hash_algo
+ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len)
 {
+   return ima_hash_algo;
 }
 
 static inline int ima_read_xattr(struct dentry *dentry,
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1d950fb..e7c7a5d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -18,7 +18,7 @@
 #include 
 #include 
 #include 
-#include 
+
 #include "ima.h"
 
 /*
@@ -188,9 +188,7 @@ int ima_get_action(struct inode *inode, int mask, int 
function)
  * Return 0 on success, error code otherwise
  */
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file,
-   struct evm_ima_xattr_data **xattr_value,
-   int *xattr_len)
+   struct file *file, enum hash_algo algo)
 {
const char *audit_cause = "failed";
struct inode *inode = file_inode(file);
@@ -201,9 +199,6 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
char digest[IMA_MAX_DIGEST_SIZE];
} hash;
 
-   if (xattr_value)
-   *xattr_len = ima_read_xattr(file->f_path.dentry, xattr_value);
-
if (!(iint->flags & IMA_COLLECTED)) {
u64 i_version = file_inode(file)->i_version;
 
@@ -213,11 +208,7 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
goto out;
}
 
-   /* use default hash algorithm */
-   hash.hdr.algo = ima_hash_algo;
-
-   if (xattr_value)
-   ima_get_hash_algo(*xattr_value, *xattr_len, );
+   hash.hdr.algo = algo;
 
result = ima_calc_file_hash(file, );
if (!result) {
diff --git a/security/integrity/ima/ima_appraise.c 
b/security/integrity/ima/ima_appraise.c
index 1873b55..9c2b46b 100644
--- a/security/integrity/ima/ima_appraise

<    1   2   3   4   5   >