linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data
@ 2020-11-01 22:26 Tushar Sugandhi
  2020-11-01 22:26 ` [PATCH v5 1/7] IMA: generalize keyring specific measurement constructs Tushar Sugandhi
                   ` (7 more replies)
  0 siblings, 8 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

There are several kernel subsystems that contain critical data which if
accidentally or maliciously altered, can compromise the integrity of the
system. Examples of such subsystems would include LSMs like SELinux, or
AppArmor; or device-mapper targets like dm-crypt, dm-verity etc. 
"critical data" in this context is kernel subsystem specific information
that is stored in kernel memory. Examples of critical data could be
kernel in-memory r/o structures, hash of the memory structures, or
data that represents a linux kernel subsystem state.

This patch set defines a new IMA hook namely CRITICAL_DATA, and a
function ima_measure_critical_data() - to measure the critical data. 
Kernel subsystems can use this functionality, to take advantage of IMA's
measuring and quoting abilities - thus ultimately enabling remote
attestation for the subsystem specific information stored in the kernel
memory.

The functionality is generic enough to measure the data of any kernel
subsystem at run-time. To ensure that only data from supported sources
are measured, the kernel subsystem needs to be added to a compile-time
list of supported sources (an "allowed list of components"). IMA
validates the source passed to ima_measure_critical_data() against this
allowed list at run-time.

System administrators may want to pick and choose which kernel
subsystem information they would want to enable for measurements,
quoting, and remote attestation. To enable that, a new IMA policy is
introduced.

This patch set also addresses the need for the kernel subsystems to
measure their data before a custom IMA policy is loaded - by providing
a builtin IMA policy.

And lastly, the use of the overall functionality is demonstrated by
measuring the kernel in-memory data for one such subsystem - SeLinux.

This series is based on the following repo/branch:

 repo: https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
 branch: next
 commit 3650b228f83a ("Linux 5.10-rc1")


Change Log v5:
(1) Incorporated feedback from Stephen on the last SeLinux patch.
 SeLinux Patch: https://patchwork.kernel.org/patch/11801585/
 - Freed memory in the reverse order of allocation in 
   selinux_measure_state().
 - Used scnprintf() instead of snprintf() to create the string for
   selinux state.
 - Allocated event name passed to ima_measure_critical_data() before
   gathering selinux state and policy information for measuring.

(2) Incorporated feedback from Mimi on v4 of this series.
 V4 of this Series: https://patchwork.kernel.org/project/linux-integrity/list/?series=354437

 - Removed patch "[v4,2/6] IMA: conditionally allow empty rule data"
 - Reversed the order of following patches.
      [v4,4/6] IMA: add policy to measure critical data from kernel components
      [v4,5/6] IMA: add hook to measure critical data from kernel components
   and renamed them to remove "from kernel components"
 - Added a new patch to this series - 
       IMA: add critical_data to built-in policy rules

 - Added the next version of SeLinux patch (mentioned above) to this
   series 
       selinux: measure state and hash of the policy using IMA

 - Updated cover-letter description to give broader perspective of the
   feature, rearranging paragraphs, removing unnecessary info, clarifying
   terms etc.
 - Got rid of opt_list param from ima_match_rule_data().
 - Updated the documentation to remove sources that don't yet exist.
 - detailed IMA hook description added to ima_measure_critical_data(),
   as well as elaborating terms event_name, event_data_source. 
 - "data_sources:=" is not a mandatory policy option for 
   func=CRITICAL_DATA anymore. If not present, all the data sources
   specified in __ima_supported_kernel_data_sources will be measured.

Change Log v4:
Incorporated feedback from Mimi on v3.
 - Split patch #1 into two patches to move introduction of bool
   allow_empty_opt_list into the 2nd patch.
 - Reverted return type of process_buffer_measurement() from int to void
   which got rid of patch #2 from the v3 of the series.
 - Renamed the policy "critical_kernel_data_sources" to "data_sources".
 - Updated process_buffer_measurement() to avoid code and variable
   duplication in the if(measure_buf_hash) block.
 - Changed return type of ima_measure_critical_data() from int to void.
 - Updated patch description for patch #3 and #4 as per Mimi's feedback.

Change Log v3:
Incorporated feedback from Mimi on v2.
 - Renamed the policy "data_sources" to
   "critical_kernel_data_sources".
 - Added "critical_kernel_data_sources" description in
   Documentation/ima-policy.
 - Split CRITICAL_DATA + critical_kernel_data_sources into two separate
   patches.
 - Merged hook ima_measure_critical_data() + CRITICAL_DATA into a single
   patch.
 - Added functionality to validate data sources before measurement.

Change Log v2:
 - Reverted the unnecessary indentations in existing #define.
 - Updated the description to replace the word 'enlightened' with
   'supported'.
 - Reverted the unnecessary rename of attribute size to buf_len.
 - Introduced a boolean parameter measure_buf_hash as per community
   feedback to support measuring hash of the buffer, instead of the
   buffer itself.

Lakshmi Ramasubramanian (2):
  IMA: add critical_data to the built-in policy rules
  selinux: measure state and hash of the policy using IMA

Tushar Sugandhi (5):
  IMA: generalize keyring specific measurement constructs
  IMA: update process_buffer_measurement to measure buffer hash
  IMA: add hook to measure critical data
  IMA: add policy to measure critical data
  IMA: validate supported kernel data sources before measurement

 Documentation/ABI/testing/ima_policy         |  10 +-
 include/linux/ima.h                          |   8 +
 security/integrity/ima/ima.h                 |  38 ++++-
 security/integrity/ima/ima_api.c             |   8 +-
 security/integrity/ima/ima_appraise.c        |   2 +-
 security/integrity/ima/ima_asymmetric_keys.c |   2 +-
 security/integrity/ima/ima_main.c            |  79 +++++++++-
 security/integrity/ima/ima_policy.c          | 143 ++++++++++++++---
 security/integrity/ima/ima_queue_keys.c      |   3 +-
 security/selinux/Makefile                    |   2 +
 security/selinux/hooks.c                     |   3 +
 security/selinux/include/security.h          |  11 +-
 security/selinux/measure.c                   | 157 +++++++++++++++++++
 security/selinux/selinuxfs.c                 |   9 ++
 security/selinux/ss/services.c               |  71 +++++++--
 15 files changed, 499 insertions(+), 47 deletions(-)
 create mode 100644 security/selinux/measure.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH v5 1/7] IMA: generalize keyring specific measurement constructs
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
@ 2020-11-01 22:26 ` Tushar Sugandhi
  2020-11-01 22:26 ` [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash Tushar Sugandhi
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

IMA functions such as ima_match_keyring(), process_buffer_measurement(),
ima_match_policy() etc. handle data specific to keyrings. Currently,
these constructs are not generic to handle any func specific data.
This makes it harder to extend them without code duplication.

Refactor the keyring specific measurement constructs to be generic and
reusable in other measurement scenarios.

Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
---
 security/integrity/ima/ima.h        |  6 ++--
 security/integrity/ima/ima_api.c    |  6 ++--
 security/integrity/ima/ima_main.c   |  6 ++--
 security/integrity/ima/ima_policy.c | 49 ++++++++++++++++++-----------
 4 files changed, 40 insertions(+), 27 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 38043074ce5e..8875085db689 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -255,7 +255,7 @@ static inline void ima_process_queued_keys(void) {}
 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
 		   int mask, enum ima_hooks func, int *pcr,
 		   struct ima_template_desc **template_desc,
-		   const char *keyring);
+		   const char *func_data);
 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, void *buf, loff_t size,
@@ -267,7 +267,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
 			   struct ima_template_desc *template_desc);
 void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 				const char *eventname, enum ima_hooks func,
-				int pcr, const char *keyring);
+				int pcr, const char *func_data);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
 			   const unsigned char *filename);
 int ima_alloc_init_template(struct ima_event_data *event_data,
@@ -283,7 +283,7 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
 int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
 		     enum ima_hooks func, int mask, int flags, int *pcr,
 		     struct ima_template_desc **template_desc,
-		     const char *keyring);
+		     const char *func_data);
 void ima_init_policy(void);
 void ima_update_policy(void);
 void ima_update_policy_flag(void);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 4f39fb93f278..af218babd198 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -170,7 +170,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
  * @func: caller identifier
  * @pcr: pointer filled in if matched measure policy sets pcr=
  * @template_desc: pointer filled in if matched measure policy sets template=
- * @keyring: keyring name used to determine the action
+ * @func_data: private data specific to @func, can be NULL.
  *
  * The policy is defined in terms of keypairs:
  *		subj=, obj=, type=, func=, mask=, fsmagic=
@@ -186,14 +186,14 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
 		   int mask, enum ima_hooks func, int *pcr,
 		   struct ima_template_desc **template_desc,
-		   const char *keyring)
+		   const char *func_data)
 {
 	int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
 
 	flags &= ima_policy_flag;
 
 	return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
-				template_desc, keyring);
+				template_desc, func_data);
 }
 
 /*
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 2d1af8899cab..ae5da9f3339d 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -786,13 +786,13 @@ int ima_post_load_data(char *buf, loff_t size,
  * @eventname: event name to be used for the buffer entry.
  * @func: IMA hook
  * @pcr: pcr to extend the measurement
- * @keyring: keyring name to determine the action to be performed
+ * @func_data: private data specific to @func, can be NULL.
  *
  * Based on policy, the buffer is measured into the ima log.
  */
 void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 				const char *eventname, enum ima_hooks func,
-				int pcr, const char *keyring)
+				int pcr, const char *func_data)
 {
 	int ret = 0;
 	const char *audit_cause = "ENOMEM";
@@ -824,7 +824,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 	if (func) {
 		security_task_getsecid(current, &secid);
 		action = ima_get_action(inode, current_cred(), secid, 0, func,
-					&pcr, &template, keyring);
+					&pcr, &template, func_data);
 		if (!(action & IMA_MEASURE))
 			return;
 	}
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 9b5adeaa47fc..4edc9be62048 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -453,30 +453,44 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
 }
 
 /**
- * ima_match_keyring - determine whether the keyring matches the measure rule
- * @rule: a pointer to a rule
- * @keyring: name of the keyring to match against the measure rule
+ * ima_match_rule_data - determine whether the given func_data matches
+ *			 the measure rule data
+ * @rule: IMA policy rule
+ * @func_data: data to match against the measure rule data
  * @cred: a pointer to a credentials structure for user validation
  *
- * Returns true if keyring matches one in the rule, false otherwise.
+ * Returns true if func_data matches one in the rule, false otherwise.
  */
-static bool ima_match_keyring(struct ima_rule_entry *rule,
-			      const char *keyring, const struct cred *cred)
+static bool ima_match_rule_data(struct ima_rule_entry *rule,
+				const char *func_data,
+				const struct cred *cred)
 {
+	const struct ima_rule_opt_list *opt_list = NULL;
 	bool matched = false;
 	size_t i;
 
 	if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
 		return false;
 
-	if (!rule->keyrings)
-		return true;
+	switch (rule->func) {
+	case KEY_CHECK:
+		if (!rule->keyrings)
+			return true;
+		else
+			opt_list = rule->keyrings;
+		break;
+	default:
+		break;
+	}
 
-	if (!keyring)
+	if (!func_data)
+		return false;
+
+	if (!opt_list)
 		return false;
 
-	for (i = 0; i < rule->keyrings->count; i++) {
-		if (!strcmp(rule->keyrings->items[i], keyring)) {
+	for (i = 0; i < opt_list->count; i++) {
+		if (!strcmp(opt_list->items[i], func_data)) {
 			matched = true;
 			break;
 		}
@@ -493,20 +507,20 @@ static bool ima_match_keyring(struct ima_rule_entry *rule,
  * @secid: the secid of the task to be validated
  * @func: LIM hook identifier
  * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
- * @keyring: keyring name to check in policy for KEY_CHECK func
+ * @func_data: private data specific to @func, can be NULL.
  *
  * Returns true on rule match, false on failure.
  */
 static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
 			    const struct cred *cred, u32 secid,
 			    enum ima_hooks func, int mask,
-			    const char *keyring)
+			    const char *func_data)
 {
 	int i;
 
 	if (func == KEY_CHECK) {
 		return (rule->flags & IMA_FUNC) && (rule->func == func) &&
-		       ima_match_keyring(rule, keyring, cred);
+			ima_match_rule_data(rule, func_data, cred);
 	}
 	if ((rule->flags & IMA_FUNC) &&
 	    (rule->func != func && func != POST_SETATTR))
@@ -610,8 +624,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
  * @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
  * @pcr: set the pcr to extend
  * @template_desc: the template that should be used for this rule
- * @keyring: the keyring name, if given, to be used to check in the policy.
- *           keyring can be NULL if func is anything other than KEY_CHECK.
+ * @func_data: private data specific to @func, can be NULL.
  *
  * Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
  * conditions.
@@ -623,7 +636,7 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
 int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
 		     enum ima_hooks func, int mask, int flags, int *pcr,
 		     struct ima_template_desc **template_desc,
-		     const char *keyring)
+		     const char *func_data)
 {
 	struct ima_rule_entry *entry;
 	int action = 0, actmask = flags | (flags << 1);
@@ -638,7 +651,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
 			continue;
 
 		if (!ima_match_rules(entry, inode, cred, secid, func, mask,
-				     keyring))
+				     func_data))
 			continue;
 
 		action |= entry->flags & IMA_ACTION_FLAGS;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
  2020-11-01 22:26 ` [PATCH v5 1/7] IMA: generalize keyring specific measurement constructs Tushar Sugandhi
@ 2020-11-01 22:26 ` Tushar Sugandhi
  2020-11-05 14:30   ` Mimi Zohar
  2020-11-06 12:11   ` Mimi Zohar
  2020-11-01 22:26 ` [PATCH v5 3/7] IMA: add hook to measure critical data Tushar Sugandhi
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

process_buffer_measurement() currently only measures the input buffer.
In case of SeLinux policy measurement, the policy being measured could
be large (several MB). This may result in a large entry in IMA
measurement log.

Introduce a boolean parameter measure_buf_hash to support measuring
hash of a buffer, which would be much smaller, instead of the buffer
itself.

To use the functionality introduced in this patch, the attestation
client and the server changes need to go hand in hand. The
client/kernel would know what data is being measured as-is
(e.g. KEXEC_CMDLINE), and what data has it’s hash measured (e.g. SeLinux
Policy). And the attestation server should verify data/hash accordingly.

Just like the data being measured in other cases, the attestation server
will know what are possible values of the large buffers being measured.
e.g. the possible valid SeLinux policy values that are being pushed to
the client. The attestation server will have to maintain the hash of
those buffer values.

Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
---
 security/integrity/ima/ima.h                 |  3 ++-
 security/integrity/ima/ima_appraise.c        |  2 +-
 security/integrity/ima/ima_asymmetric_keys.c |  2 +-
 security/integrity/ima/ima_main.c            | 25 ++++++++++++++++++--
 security/integrity/ima/ima_queue_keys.c      |  3 ++-
 5 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 8875085db689..0f77e0b697a3 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -267,7 +267,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
 			   struct ima_template_desc *template_desc);
 void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 				const char *eventname, enum ima_hooks func,
-				int pcr, const char *func_data);
+				int pcr, const char *func_data,
+				bool measure_buf_hash);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
 			   const unsigned char *filename);
 int ima_alloc_init_template(struct ima_event_data *event_data,
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 3dd8c2e4314e..be64c0bf62a7 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -347,7 +347,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
 		if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
 			process_buffer_measurement(NULL, digest, digestsize,
 						   "blacklisted-hash", NONE,
-						   pcr, NULL);
+						   pcr, NULL, false);
 	}
 
 	return rc;
diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
index 1c68c500c26f..a74095793936 100644
--- a/security/integrity/ima/ima_asymmetric_keys.c
+++ b/security/integrity/ima/ima_asymmetric_keys.c
@@ -60,5 +60,5 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
 	 */
 	process_buffer_measurement(NULL, payload, payload_len,
 				   keyring->description, KEY_CHECK, 0,
-				   keyring->description);
+				   keyring->description, false);
 }
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index ae5da9f3339d..4485d87c0aa5 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -787,12 +787,15 @@ int ima_post_load_data(char *buf, loff_t size,
  * @func: IMA hook
  * @pcr: pcr to extend the measurement
  * @func_data: private data specific to @func, can be NULL.
+ * @measure_buf_hash: if set to true - will measure hash of the buf,
+ *                    instead of buf
  *
  * Based on policy, the buffer is measured into the ima log.
  */
 void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 				const char *eventname, enum ima_hooks func,
-				int pcr, const char *func_data)
+				int pcr, const char *func_data,
+				bool measure_buf_hash)
 {
 	int ret = 0;
 	const char *audit_cause = "ENOMEM";
@@ -807,6 +810,8 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 		struct ima_digest_data hdr;
 		char digest[IMA_MAX_DIGEST_SIZE];
 	} hash = {};
+	char digest_hash[IMA_MAX_DIGEST_SIZE];
+	int hash_len = hash_digest_size[ima_hash_algo];
 	int violation = 0;
 	int action = 0;
 	u32 secid;
@@ -855,6 +860,21 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 		goto out;
 	}
 
+	if (measure_buf_hash) {
+		memcpy(digest_hash, hash.hdr.digest, hash_len);
+
+		ret = ima_calc_buffer_hash(digest_hash,
+					   hash_len,
+					   iint.ima_hash);
+		if (ret < 0) {
+			audit_cause = "measure_buf_hash_error";
+			goto out;
+		}
+
+		event_data.buf = digest_hash;
+		event_data.buf_len = hash_len;
+	}
+
 	ret = ima_alloc_init_template(&event_data, &entry, template);
 	if (ret < 0) {
 		audit_cause = "alloc_entry";
@@ -896,7 +916,8 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
 		return;
 
 	process_buffer_measurement(file_inode(f.file), buf, size,
-				   "kexec-cmdline", KEXEC_CMDLINE, 0, NULL);
+				   "kexec-cmdline", KEXEC_CMDLINE, 0, NULL,
+				   false);
 	fdput(f);
 }
 
diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c
index 69a8626a35c0..c2f2ad34f9b7 100644
--- a/security/integrity/ima/ima_queue_keys.c
+++ b/security/integrity/ima/ima_queue_keys.c
@@ -162,7 +162,8 @@ void ima_process_queued_keys(void)
 						   entry->payload_len,
 						   entry->keyring_name,
 						   KEY_CHECK, 0,
-						   entry->keyring_name);
+						   entry->keyring_name,
+						   false);
 		list_del(&entry->list);
 		ima_free_key_entry(entry);
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v5 3/7] IMA: add hook to measure critical data
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
  2020-11-01 22:26 ` [PATCH v5 1/7] IMA: generalize keyring specific measurement constructs Tushar Sugandhi
  2020-11-01 22:26 ` [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash Tushar Sugandhi
@ 2020-11-01 22:26 ` Tushar Sugandhi
  2020-11-06 13:24   ` Mimi Zohar
  2020-11-01 22:26 ` [PATCH v5 4/7] IMA: add policy " Tushar Sugandhi
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Currently, IMA does not provide a generic function for kernel subsystems
to measure their critical data. Examples of critical data in this context
could be kernel in-memory r/o structures, hash of the memory structures,
or data that represents a linux kernel subsystem state change. The 
critical data, if accidentally or maliciously altered, can compromise
the integrity of the system.

A generic function provided by IMA to measure critical data would enable
various subsystems with easier and faster on-boarding to use IMA
infrastructure and would also avoid code duplication.

Add a new IMA func CRITICAL_DATA and a corresponding IMA hook
ima_measure_critical_data() to support measuring critical data for 
various kernel subsystems. 

Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
---
 Documentation/ABI/testing/ima_policy |  2 +-
 include/linux/ima.h                  |  8 ++++++
 security/integrity/ima/ima.h         |  1 +
 security/integrity/ima/ima_api.c     |  2 +-
 security/integrity/ima/ima_main.c    | 38 ++++++++++++++++++++++++++++
 security/integrity/ima/ima_policy.c  |  2 ++
 6 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index cd572912c593..3de6c774c37e 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -29,7 +29,7 @@ Description:
 		base: 	func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
 				[FIRMWARE_CHECK]
 				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
-				[KEXEC_CMDLINE] [KEY_CHECK]
+				[KEXEC_CMDLINE] [KEY_CHECK] [CRITICAL_DATA]
 			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 8fa7bcfb2da2..60ba073f1575 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -30,6 +30,10 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
 extern void ima_post_path_mknod(struct dentry *dentry);
 extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
 extern void ima_kexec_cmdline(int kernel_fd, const void *buf, int size);
+extern void ima_measure_critical_data(const char *event_data_source,
+				      const char *event_name,
+				      const void *buf, int buf_len,
+				      bool measure_buf_hash);
 
 #ifdef CONFIG_IMA_KEXEC
 extern void ima_add_kexec_buffer(struct kimage *image);
@@ -116,6 +120,10 @@ static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size)
 }
 
 static inline void ima_kexec_cmdline(int kernel_fd, const void *buf, int size) {}
+static inline void ima_measure_critical_data(const char *event_data_source,
+					     const char *event_name,
+					     const void *buf, int buf_len,
+					     bool measure_buf_hash) {}
 #endif /* CONFIG_IMA */
 
 #ifndef CONFIG_IMA_KEXEC
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 0f77e0b697a3..c1acf88e1b5d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -200,6 +200,7 @@ static inline unsigned int ima_hash_key(u8 *digest)
 	hook(POLICY_CHECK, policy)			\
 	hook(KEXEC_CMDLINE, kexec_cmdline)		\
 	hook(KEY_CHECK, key)				\
+	hook(CRITICAL_DATA, critical_data)		\
 	hook(MAX_CHECK, none)
 
 #define __ima_hook_enumify(ENUM, str)	ENUM,
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index af218babd198..9917e1730cb6 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -176,7 +176,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
  *		subj=, obj=, type=, func=, mask=, fsmagic=
  *	subj,obj, and type: are LSM specific.
  *	func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
- *	| KEXEC_CMDLINE | KEY_CHECK
+ *	| KEXEC_CMDLINE | KEY_CHECK | CRITICAL_DATA
  *	mask: contains the permission mask
  *	fsmagic: hex value
  *
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 4485d87c0aa5..6e1b11dcba53 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -921,6 +921,44 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
 	fdput(f);
 }
 
+/**
+ * ima_measure_critical_data - measure kernel subsystem data
+ * critical to integrity of the kernel
+ * @event_data_source: name of the data source being measured;
+ * typically it should be the name of the kernel subsystem that is sending
+ * the data for measurement
+ * @event_name: name of an event from the kernel subsystem that is sending
+ * the data for measurement
+ * @buf: pointer to buffer containing data to measure
+ * @buf_len: length of buffer(in bytes)
+ * @measure_buf_hash: if set to true - will measure hash of the buf,
+ *                    instead of buf
+ *
+ * A given kernel subsystem (event_data_source) may send
+ * data (buf) to be measured when the data or the subsystem state changes.
+ * The state/data change can be described by event_name.
+ * Examples of critical data (buf) could be kernel in-memory r/o structures,
+ * hash of the memory structures, or data that represents subsystem
+ * state change.
+ * measure_buf_hash can be used to save space, if the data being measured
+ * is too large.
+ * The data (buf) can only be measured, not appraised.
+ */
+void ima_measure_critical_data(const char *event_data_source,
+			       const char *event_name,
+			       const void *buf, int buf_len,
+			       bool measure_buf_hash)
+{
+	if (!event_name || !event_data_source || !buf || !buf_len) {
+		pr_err("Invalid arguments passed to %s().\n", __func__);
+		return;
+	}
+
+	process_buffer_measurement(NULL, buf, buf_len, event_name,
+				   CRITICAL_DATA, 0, event_data_source,
+				   measure_buf_hash);
+}
+
 static int __init init_ima(void)
 {
 	int error;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 4edc9be62048..f48e82450fe1 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -1251,6 +1251,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 			else if (IS_ENABLED(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) &&
 				 strcmp(args[0].from, "KEY_CHECK") == 0)
 				entry->func = KEY_CHECK;
+			else if (strcmp(args[0].from, "CRITICAL_DATA") == 0)
+				entry->func = CRITICAL_DATA;
 			else
 				result = -EINVAL;
 			if (!result)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v5 4/7] IMA: add policy to measure critical data
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
                   ` (2 preceding siblings ...)
  2020-11-01 22:26 ` [PATCH v5 3/7] IMA: add hook to measure critical data Tushar Sugandhi
@ 2020-11-01 22:26 ` Tushar Sugandhi
  2020-11-06 13:43   ` Mimi Zohar
  2020-11-01 22:26 ` [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement Tushar Sugandhi
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

System administrators should be able to choose which kernel subsystems
they want to measure the critical data for. To enable that, an IMA policy
option to choose specific kernel subsystems is needed. This policy option
would constrain the measurement of the critical data to the given kernel
subsystems.

Add a new IMA policy option - "data_sources:=" to the IMA func 
CRITICAL_DATA to allow measurement of various kernel subsystems. This
policy option would enable the system administrators to limit the
measurement to the subsystems listed in "data_sources:=", if the 
subsystem measures its data by calling ima_measure_critical_data().

Limit the measurement to the subsystems that are specified in the IMA
policy - CRITICAL_DATA+"data_sources:=". If "data_sources:=" is not
provided with the func CRITICAL_DATA, measure the data from all the
supported kernel subsystems.

Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
---
 Documentation/ABI/testing/ima_policy |  4 ++
 security/integrity/ima/ima_policy.c  | 62 +++++++++++++++++++++++++---
 2 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 3de6c774c37e..15be8b16f6f3 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -48,6 +48,10 @@ Description:
 			template:= name of a defined IMA template type
 			(eg, ima-ng). Only valid when action is "measure".
 			pcr:= decimal value
+			data_sources:= list of kernel subsystems that contain
+			kernel in-memory data critical to the integrity of the kernel.
+			Only valid when action is "measure" and func is
+			CRITICAL_DATA.
 
 		default policy:
 			# PROC_SUPER_MAGIC
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index f48e82450fe1..ec99e0bb6c6f 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -34,6 +34,7 @@
 #define IMA_PCR		0x0100
 #define IMA_FSNAME	0x0200
 #define IMA_KEYRINGS	0x0400
+#define IMA_DATA_SOURCES	0x0800
 
 #define UNKNOWN		0
 #define MEASURE		0x0001	/* same as IMA_MEASURE */
@@ -85,6 +86,7 @@ struct ima_rule_entry {
 	} lsm[MAX_LSM_RULES];
 	char *fsname;
 	struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */
+	struct ima_rule_opt_list *data_sources; /* Measure data from these sources */
 	struct ima_template_desc *template;
 };
 
@@ -479,6 +481,12 @@ static bool ima_match_rule_data(struct ima_rule_entry *rule,
 		else
 			opt_list = rule->keyrings;
 		break;
+	case CRITICAL_DATA:
+		if (!rule->data_sources)
+			return true;
+		else
+			opt_list = rule->data_sources;
+		break;
 	default:
 		break;
 	}
@@ -518,13 +526,19 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
 {
 	int i;
 
-	if (func == KEY_CHECK) {
-		return (rule->flags & IMA_FUNC) && (rule->func == func) &&
-			ima_match_rule_data(rule, func_data, cred);
-	}
 	if ((rule->flags & IMA_FUNC) &&
 	    (rule->func != func && func != POST_SETATTR))
 		return false;
+
+	switch (func) {
+	case KEY_CHECK:
+	case CRITICAL_DATA:
+		return ((rule->func == func) &&
+			ima_match_rule_data(rule, func_data, cred));
+	default:
+		break;
+	}
+
 	if ((rule->flags & IMA_MASK) &&
 	    (rule->mask != mask && func != POST_SETATTR))
 		return false;
@@ -920,7 +934,7 @@ enum {
 	Opt_uid_lt, Opt_euid_lt, Opt_fowner_lt,
 	Opt_appraise_type, Opt_appraise_flag,
 	Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings,
-	Opt_err
+	Opt_data_sources, Opt_err
 };
 
 static const match_table_t policy_tokens = {
@@ -957,6 +971,7 @@ static const match_table_t policy_tokens = {
 	{Opt_pcr, "pcr=%s"},
 	{Opt_template, "template=%s"},
 	{Opt_keyrings, "keyrings=%s"},
+	{Opt_data_sources, "data_sources=%s"},
 	{Opt_err, NULL}
 };
 
@@ -1119,6 +1134,19 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
 		if (ima_rule_contains_lsm_cond(entry))
 			return false;
 
+		break;
+	case CRITICAL_DATA:
+		if (entry->action & ~(MEASURE | DONT_MEASURE))
+			return false;
+
+		if (!(entry->flags & IMA_DATA_SOURCES) ||
+		    (entry->flags & ~(IMA_FUNC | IMA_UID | IMA_PCR |
+		    IMA_DATA_SOURCES)))
+			return false;
+
+		if (ima_rule_contains_lsm_cond(entry))
+			return false;
+
 		break;
 	default:
 		return false;
@@ -1323,6 +1351,24 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 
 			entry->flags |= IMA_KEYRINGS;
 			break;
+		case Opt_data_sources:
+			ima_log_string(ab, "data_sources",
+				       args[0].from);
+
+			if (entry->data_sources) {
+				result = -EINVAL;
+				break;
+			}
+
+			entry->data_sources = ima_alloc_rule_opt_list(args);
+			if (IS_ERR(entry->data_sources)) {
+				result = PTR_ERR(entry->data_sources);
+				entry->data_sources = NULL;
+				break;
+			}
+
+			entry->flags |= IMA_DATA_SOURCES;
+			break;
 		case Opt_fsuuid:
 			ima_log_string(ab, "fsuuid", args[0].from);
 
@@ -1703,6 +1749,12 @@ int ima_policy_show(struct seq_file *m, void *v)
 		seq_puts(m, " ");
 	}
 
+	if (entry->flags & IMA_DATA_SOURCES) {
+		seq_puts(m, "data_sources=");
+		ima_show_rule_opt_list(m, entry->data_sources);
+		seq_puts(m, " ");
+	}
+
 	if (entry->flags & IMA_PCR) {
 		snprintf(tbuf, sizeof(tbuf), "%d", entry->pcr);
 		seq_printf(m, pt(Opt_pcr), tbuf);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
                   ` (3 preceding siblings ...)
  2020-11-01 22:26 ` [PATCH v5 4/7] IMA: add policy " Tushar Sugandhi
@ 2020-11-01 22:26 ` Tushar Sugandhi
  2020-11-06 14:01   ` Mimi Zohar
  2020-11-01 22:26 ` [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules Tushar Sugandhi
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Currently, IMA does not restrict random data sources from measuring
their data using ima_measure_critical_data(). Any kernel data source can
call the function, and it's data will get measured as long as the input
event_data_source is part of the IMA policy - CRITICAL_DATA+data_sources.

To ensure that only data from supported sources are measured, the kernel
subsystem name needs to be added to a compile-time list of supported
sources (an "allowed list of components"). IMA then validates the input
parameter - "event_data_source" passed to ima_measure_critical_data()
against this allowed list at run-time.

This compile-time list must be updated when kernel subsystems are
updated to measure their data using IMA.

Provide an infrastructure for kernel data sources to be added to
IMA's supported data sources list at compile-time. Update
ima_measure_critical_data() to validate, at run-time, that the data
source is supported before measuring the data coming from that source.

Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
---
 security/integrity/ima/ima.h      | 29 +++++++++++++++++++++++++++++
 security/integrity/ima/ima_main.c | 12 ++++++++++++
 2 files changed, 41 insertions(+)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c1acf88e1b5d..4a35db010d91 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -228,6 +228,35 @@ extern const char *const func_tokens[];
 
 struct modsig;
 
+#define __ima_supported_kernel_data_sources(source)	\
+	source(MIN_SOURCE, min_source)			\
+	source(MAX_SOURCE, max_source)
+
+#define __ima_enum_stringify(ENUM, str) (#str),
+
+enum ima_supported_kernel_data_sources {
+	__ima_supported_kernel_data_sources(__ima_hook_enumify)
+};
+
+static const char * const ima_supported_kernel_data_sources_str[] = {
+	__ima_supported_kernel_data_sources(__ima_enum_stringify)
+};
+
+static inline bool ima_kernel_data_source_is_supported(const char *source)
+{
+	int i;
+
+	if (!source)
+		return false;
+
+	for (i = MIN_SOURCE + 1; i < MAX_SOURCE; i++) {
+		if (!strcmp(ima_supported_kernel_data_sources_str[i], source))
+			return true;
+	}
+
+	return false;
+}
+
 #ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS
 /*
  * To track keys that need to be measured.
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 6e1b11dcba53..091c2e58f3c7 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -937,6 +937,12 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
  * A given kernel subsystem (event_data_source) may send
  * data (buf) to be measured when the data or the subsystem state changes.
  * The state/data change can be described by event_name.
+ * Before the first use of this function by a given kernel subsystem,
+ * the subsystem name (event_data_source) must be added to the
+ * compile-time list of data sources being measured -
+ * i.e. __ima_supported_kernel_data_sources.
+ * Otherwise, IMA will not measure any data for that event_data_source
+ * at run-time.
  * Examples of critical data (buf) could be kernel in-memory r/o structures,
  * hash of the memory structures, or data that represents subsystem
  * state change.
@@ -954,6 +960,12 @@ void ima_measure_critical_data(const char *event_data_source,
 		return;
 	}
 
+	if (!ima_kernel_data_source_is_supported(event_data_source)) {
+		pr_err("measuring data source %s is not permitted",
+		       event_data_source);
+		return;
+	}
+
 	process_buffer_measurement(NULL, buf, buf_len, event_name,
 				   CRITICAL_DATA, 0, event_data_source,
 				   measure_buf_hash);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
                   ` (4 preceding siblings ...)
  2020-11-01 22:26 ` [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement Tushar Sugandhi
@ 2020-11-01 22:26 ` Tushar Sugandhi
  2020-11-06 15:24   ` Mimi Zohar
  2020-11-01 22:26 ` [PATCH v5 7/7] selinux: measure state and hash of the policy using IMA Tushar Sugandhi
  2020-11-05  0:31 ` [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Mimi Zohar
  7 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

From: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>

The IMA hook to measure kernel critical data, namely
ima_measure_critical_data(), could be called before a custom IMA policy
is loaded. For example, SELinux calls ima_measure_critical_data() to
measure its state and policy when they are initialized. This occurs
before a custom IMA policy is loaded, and hence IMA hook will not
measure the data. A built-in policy is therefore needed to measure
critical data provided by callers before a custom IMA policy is loaded.

Add CRITICAL_DATA to built-in IMA rules if the kernel command line
contains "ima_policy=critical_data". Set the IMA template for this rule
to "ima-buf" since ima_measure_critical_data() measures a buffer.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 security/integrity/ima/ima_policy.c | 32 +++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index ec99e0bb6c6f..dc8fe969d3fe 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -206,6 +206,10 @@ static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
 	 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
 };
 
+static struct ima_rule_entry critical_data_rules[] __ro_after_init = {
+	{.action = MEASURE, .func = CRITICAL_DATA, .flags = IMA_FUNC},
+};
+
 /* An array of architecture specific rules */
 static struct ima_rule_entry *arch_policy_entry __ro_after_init;
 
@@ -228,6 +232,7 @@ __setup("ima_tcb", default_measure_policy_setup);
 
 static bool ima_use_appraise_tcb __initdata;
 static bool ima_use_secure_boot __initdata;
+static bool ima_use_critical_data __ro_after_init;
 static bool ima_fail_unverifiable_sigs __ro_after_init;
 static int __init policy_setup(char *str)
 {
@@ -242,6 +247,8 @@ static int __init policy_setup(char *str)
 			ima_use_appraise_tcb = true;
 		else if (strcmp(p, "secure_boot") == 0)
 			ima_use_secure_boot = true;
+		else if (strcmp(p, "critical_data") == 0)
+			ima_use_critical_data = true;
 		else if (strcmp(p, "fail_securely") == 0)
 			ima_fail_unverifiable_sigs = true;
 		else
@@ -813,6 +820,8 @@ static int __init ima_init_arch_policy(void)
 void __init ima_init_policy(void)
 {
 	int build_appraise_entries, arch_entries;
+	struct ima_template_desc *template = NULL;
+	int ret = 0;
 
 	/* if !ima_policy, we load NO default rules */
 	if (ima_policy)
@@ -875,6 +884,29 @@ void __init ima_init_policy(void)
 			  ARRAY_SIZE(default_appraise_rules),
 			  IMA_DEFAULT_POLICY);
 
+	if (ima_use_critical_data) {
+		template = lookup_template_desc("ima-buf");
+		if (!template) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		ret = template_desc_init_fields(template->fmt,
+						&(template->fields),
+						&(template->num_fields));
+		if (ret)
+			goto out;
+
+		critical_data_rules[0].template = template;
+		add_rules(critical_data_rules,
+			  ARRAY_SIZE(critical_data_rules),
+			  IMA_DEFAULT_POLICY);
+	}
+
+out:
+	if (ret)
+		pr_err("%s failed, result: %d\n", __func__, ret);
+
 	ima_update_policy_flag();
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH v5 7/7] selinux: measure state and hash of the policy using IMA
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
                   ` (5 preceding siblings ...)
  2020-11-01 22:26 ` [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules Tushar Sugandhi
@ 2020-11-01 22:26 ` Tushar Sugandhi
  2020-11-06 15:47   ` Mimi Zohar
  2020-11-05  0:31 ` [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Mimi Zohar
  7 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-01 22:26 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

From: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>

Critical data structures of security modules are currently not measured.
Therefore an attestation service, for instance, would not be able to
attest whether the security modules are always operating with the policies
and configurations that the system administrator had setup. The policies
and configurations for the security modules could be tampered by rogue
user mode agents or modified through some inadvertent actions on
the system. Measuring such critical data would enable an attestation
service to reliably assess the security configuration of the system.

SELinux configuration and policy are some of the critical data for this
security module that need to be measured. This measurement can be used
by an attestation service, for instance, to verify if the configurations
and policies have been setup correctly and that they haven't been
tampered at run-time.

Measure SELinux configurations, policy capabilities settings, and
the hash of the loaded policy by calling the IMA hook
ima_measure_critical_data(). Since the size of the loaded policy can
be large (several MB), measure the hash of the policy instead of
the entire policy to avoid bloating the IMA log entry.

Add "selinux" to the list of supported data sources maintained by IMA
to enable measuring SELinux data.

To enable SELinux data measurement, the following steps are required:

1, Add "ima_policy=critical_data" to the kernel command line arguments
   to enable measuring SELinux data at boot time.
For example,
  BOOT_IMAGE=/boot/vmlinuz-5.10.0-rc1+ root=UUID=fd643309-a5d2-4ed3-b10d-3c579a5fab2f ro nomodeset security=selinux ima_policy=critical_data

2, Add the following rule to /etc/ima/ima-policy
   measure func=CRITICAL_DATA data_sources=selinux template=ima-buf

Sample measurement of SELinux state and hash of the policy:

10 e32e...5ac3 ima-buf sha256:86e8...4594 selinux-state-1595389364:287899386 696e697469616c697a65643d313b656e61626c65643d313b656e666f7263696e673d303b636865636b72657170726f743d313b6e6574776f726b5f706565725f636f6e74726f6c733d313b6f70656e5f7065726d733d313b657874656e6465645f736f636b65745f636c6173733d313b616c776179735f636865636b5f6e6574776f726b3d303b6367726f75705f7365636c6162656c3d313b6e6e705f6e6f737569645f7472616e736974696f6e3d313b67656e66735f7365636c6162656c5f73796d6c696e6b733d303
10 9e81...0857 ima-buf sha256:4941...68fc selinux-policy-hash-1597335667:462051628 8d1d...1834

To verify the measurement check the following:

Execute the following command to extract the measured data
from the IMA log for SELinux configuration (selinux-state).

  grep "selinux-state" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | tail -1 | cut -d' ' -f 6 | xxd -r -p

The output should be the list of key-value pairs. For example,
 initialized=1;enabled=1;enforcing=0;checkreqprot=1;network_peer_controls=1;open_perms=1;extended_socket_class=1;always_check_network=0;cgroup_seclabel=1;nnp_nosuid_transition=1;genfs_seclabel_symlinks=0;

To verify the measured data with the current SELinux state:

 => enabled should be set to 1 if /sys/fs/selinux folder exists,
    0 otherwise

For other entries, compare the integer value in the files
 => /sys/fs/selinux/enforce
 => /sys/fs/selinux/checkreqprot
And, each of the policy capabilities files under
 => /sys/fs/selinux/policy_capabilities

Note that the actual verification would be against an expected state
and done on a system other than the measured system, typically
requiring "initialized=1; enabled=1;enforcing=1;checkreqprot=0;" for
a secure state and then whatever policy capabilities are actually set
in the expected policy (which can be extracted from the policy itself
via seinfo, for example).

For selinux-policy-hash, the hash of SELinux policy is included
in the IMA log entry.

To verify the measured data with the current SELinux policy run
the following commands and verify the output hash values match.

  sha256sum /sys/fs/selinux/policy | cut -d' ' -f 1

  grep "selinux-policy-hash" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | tail -1 | cut -d' ' -f 6

Note that the actual verification of SELinux policy would require loading
the expected policy into an identical kernel on a pristine/known-safe
system and run the sha256sum /sys/kernel/selinux/policy there to get
the expected hash.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
---
 Documentation/ABI/testing/ima_policy |   6 +-
 security/integrity/ima/ima.h         |   1 +
 security/selinux/Makefile            |   2 +
 security/selinux/hooks.c             |   3 +
 security/selinux/include/security.h  |  11 +-
 security/selinux/measure.c           | 157 +++++++++++++++++++++++++++
 security/selinux/selinuxfs.c         |   9 ++
 security/selinux/ss/services.c       |  71 ++++++++++--
 8 files changed, 249 insertions(+), 11 deletions(-)
 create mode 100644 security/selinux/measure.c

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 15be8b16f6f3..2eb06c53a326 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -48,7 +48,7 @@ Description:
 			template:= name of a defined IMA template type
 			(eg, ima-ng). Only valid when action is "measure".
 			pcr:= decimal value
-			data_sources:= list of kernel subsystems that contain
+			data_sources:= list of kernel subsystems (eg, SeLinux) that contain
 			kernel in-memory data critical to the integrity of the kernel.
 			Only valid when action is "measure" and func is
 			CRITICAL_DATA.
@@ -129,3 +129,7 @@ Description:
 		keys added to .builtin_trusted_keys or .ima keyring:
 
 			measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima
+
+		Example of measure rule using CRITICAL_DATA to measure critical data
+
+			measure func=CRITICAL_DATA data_sources=selinux template=ima-buf
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 4a35db010d91..f10b9a368595 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -230,6 +230,7 @@ struct modsig;
 
 #define __ima_supported_kernel_data_sources(source)	\
 	source(MIN_SOURCE, min_source)			\
+	source(SELINUX, selinux)			\
 	source(MAX_SOURCE, max_source)
 
 #define __ima_enum_stringify(ENUM, str) (#str),
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index 4d8e0e8adf0b..83d512116341 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -16,6 +16,8 @@ selinux-$(CONFIG_NETLABEL) += netlabel.o
 
 selinux-$(CONFIG_SECURITY_INFINIBAND) += ibpkey.o
 
+selinux-$(CONFIG_IMA) += measure.o
+
 ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
 
 $(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6b1826fc3658..8b9fde47ae28 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7398,6 +7398,9 @@ int selinux_disable(struct selinux_state *state)
 	}
 
 	selinux_mark_disabled(state);
+	mutex_lock(&state->policy_mutex);
+	selinux_measure_state(state);
+	mutex_unlock(&state->policy_mutex);
 
 	pr_info("SELinux:  Disabled at runtime.\n");
 
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 3cc8bab31ea8..18ee65c98446 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -229,7 +229,8 @@ void selinux_policy_cancel(struct selinux_state *state,
 			struct selinux_policy *policy);
 int security_read_policy(struct selinux_state *state,
 			 void **data, size_t *len);
-
+int security_read_policy_kernel(struct selinux_state *state,
+				void **data, size_t *len);
 int security_policycap_supported(struct selinux_state *state,
 				 unsigned int req_cap);
 
@@ -446,4 +447,12 @@ extern void ebitmap_cache_init(void);
 extern void hashtab_cache_init(void);
 extern int security_sidtab_hash_stats(struct selinux_state *state, char *page);
 
+#ifdef CONFIG_IMA
+extern void selinux_measure_state(struct selinux_state *selinux_state);
+#else
+static inline void selinux_measure_state(struct selinux_state *selinux_state)
+{
+}
+#endif
+
 #endif /* _SELINUX_SECURITY_H_ */
diff --git a/security/selinux/measure.c b/security/selinux/measure.c
new file mode 100644
index 000000000000..65d42059f588
--- /dev/null
+++ b/security/selinux/measure.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Measure SELinux state using IMA subsystem.
+ */
+#include <linux/vmalloc.h>
+#include <linux/ktime.h>
+#include <linux/ima.h>
+#include "security.h"
+
+/*
+ * This function creates a unique name by appending the timestamp to
+ * the given string. This string is passed as "event_name" to the IMA
+ * hook to measure the given SELinux data.
+ *
+ * The data provided by SELinux to the IMA subsystem for measuring may have
+ * already been measured (for instance the same state existed earlier).
+ * But for SELinux the current data represents a state change and hence
+ * needs to be measured again. To enable this, pass a unique "event_name"
+ * to the IMA hook so that IMA subsystem will always measure the given data.
+ *
+ * For example,
+ * At time T0 SELinux data to be measured is "foo". IMA measures it.
+ * At time T1 the data is changed to "bar". IMA measures it.
+ * At time T2 the data is changed to "foo" again. IMA will not measure it
+ * (since it was already measured) unless the event_name, for instance,
+ * is different in this call.
+ */
+static char *selinux_event_name(const char *name_prefix)
+{
+	char *event_name = NULL;
+	struct timespec64 cur_time;
+
+	ktime_get_real_ts64(&cur_time);
+	event_name = kasprintf(GFP_KERNEL, "%s-%lld:%09ld", name_prefix,
+			       cur_time.tv_sec, cur_time.tv_nsec);
+	if (!event_name) {
+		pr_err("%s: event name not allocated.\n", __func__);
+		return NULL;
+	}
+
+	return event_name;
+}
+
+static int read_selinux_state(char **state_str, int *state_str_len,
+			      struct selinux_state *state)
+{
+	char *buf, *str_fmt = "%s=%d;";
+	int i, buf_len, curr;
+	bool initialized = selinux_initialized(state);
+	bool enabled = !selinux_disabled(state);
+	bool enforcing = enforcing_enabled(state);
+	bool checkreqprot = checkreqprot_get(state);
+
+	buf_len = snprintf(NULL, 0, str_fmt, "initialized", initialized);
+	buf_len += snprintf(NULL, 0, str_fmt, "enabled", enabled);
+	buf_len += snprintf(NULL, 0, str_fmt, "enforcing", enforcing);
+	buf_len += snprintf(NULL, 0, str_fmt, "checkreqprot", checkreqprot);
+
+	for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) {
+		buf_len += snprintf(NULL, 0, str_fmt,
+				    selinux_policycap_names[i],
+				    state->policycap[i]);
+	}
+	++buf_len;
+
+	buf = kzalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	curr = scnprintf(buf, buf_len, str_fmt,
+			 "initialized", initialized);
+	curr += scnprintf((buf + curr), (buf_len - curr), str_fmt,
+			  "enabled", enabled);
+	curr += scnprintf((buf + curr), (buf_len - curr), str_fmt,
+			  "enforcing", enforcing);
+	curr += scnprintf((buf + curr), (buf_len - curr), str_fmt,
+			  "checkreqprot", checkreqprot);
+
+	for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) {
+		curr += scnprintf((buf + curr), (buf_len - curr), str_fmt,
+				  selinux_policycap_names[i],
+				  state->policycap[i]);
+	}
+
+	*state_str = buf;
+	*state_str_len = curr;
+
+	return 0;
+}
+
+/*
+ * selinux_measure_state - Measure SELinux state configuration and hash of
+ *			   the SELinux policy.
+ * @state: selinux state struct
+ *
+ * NOTE: This function must be called with policy_mutex held.
+ */
+void selinux_measure_state(struct selinux_state *state)
+{
+	void *policy = NULL;
+	char *state_event_name = NULL;
+	char *policy_event_name = NULL;
+	char *state_str = NULL;
+	size_t policy_len;
+	int state_str_len, rc = 0;
+	bool initialized = selinux_initialized(state);
+
+	/*
+	 * Get a unique string for measuring the current SELinux state.
+	 */
+	state_event_name = selinux_event_name("selinux-state");
+	if (!state_event_name) {
+		pr_err("%s: Event name for state not allocated.\n",
+		       __func__);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = read_selinux_state(&state_str, &state_str_len, state);
+	if (rc) {
+		pr_err("%s: Failed to read state %d.\n", __func__, rc);
+		goto out;
+	}
+
+	ima_measure_critical_data("selinux", state_event_name,
+				  state_str, state_str_len, false);
+
+	/*
+	 * Measure SELinux policy only after initialization is completed.
+	 */
+	if (!initialized)
+		goto out;
+
+	policy_event_name = selinux_event_name("selinux-policy-hash");
+	if (!policy_event_name) {
+		pr_err("%s: Event name for policy not allocated.\n",
+		       __func__);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = security_read_policy_kernel(state, &policy, &policy_len);
+	if (rc) {
+		pr_err("%s: Failed to read policy %d.\n", __func__, rc);
+		goto out;
+	}
+
+	ima_measure_critical_data("selinux", policy_event_name,
+				  policy, policy_len, true);
+
+	vfree(policy);
+
+out:
+	kfree(policy_event_name);
+	kfree(state_str);
+	kfree(state_event_name);
+}
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 4bde570d56a2..a4f1282f7178 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -182,6 +182,10 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
 		selinux_status_update_setenforce(state, new_value);
 		if (!new_value)
 			call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
+
+		mutex_lock(&state->policy_mutex);
+		selinux_measure_state(state);
+		mutex_unlock(&state->policy_mutex);
 	}
 	length = count;
 out:
@@ -762,6 +766,11 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
 
 	checkreqprot_set(fsi->state, (new_value ? 1 : 0));
 	length = count;
+
+	mutex_lock(&fsi->state->policy_mutex);
+	selinux_measure_state(fsi->state);
+	mutex_unlock(&fsi->state->policy_mutex);
+
 out:
 	kfree(page);
 	return length;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 9704c8a32303..dfa2e00894ae 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2180,6 +2180,7 @@ static void selinux_notify_policy_change(struct selinux_state *state,
 	selinux_status_update_policyload(state, seqno);
 	selinux_netlbl_cache_invalidate();
 	selinux_xfrm_notify_policyload();
+	selinux_measure_state(state);
 }
 
 void selinux_policy_commit(struct selinux_state *state,
@@ -3875,8 +3876,33 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
 }
 #endif /* CONFIG_NETLABEL */
 
+/**
+ * security_read_selinux_policy - read the policy.
+ * @policy: SELinux policy
+ * @data: binary policy data
+ * @len: length of data in bytes
+ *
+ */
+static int security_read_selinux_policy(struct selinux_policy *policy,
+					void *data, size_t *len)
+{
+	int rc;
+	struct policy_file fp;
+
+	fp.data = data;
+	fp.len = *len;
+
+	rc = policydb_write(&policy->policydb, &fp);
+	if (rc)
+		return rc;
+
+	*len = (unsigned long)fp.data - (unsigned long)data;
+	return 0;
+}
+
 /**
  * security_read_policy - read the policy.
+ * @state: selinux_state
  * @data: binary policy data
  * @len: length of data in bytes
  *
@@ -3885,8 +3911,6 @@ int security_read_policy(struct selinux_state *state,
 			 void **data, size_t *len)
 {
 	struct selinux_policy *policy;
-	int rc;
-	struct policy_file fp;
 
 	policy = rcu_dereference_protected(
 			state->policy, lockdep_is_held(&state->policy_mutex));
@@ -3898,14 +3922,43 @@ int security_read_policy(struct selinux_state *state,
 	if (!*data)
 		return -ENOMEM;
 
-	fp.data = *data;
-	fp.len = *len;
+	return security_read_selinux_policy(policy, *data, len);
+}
 
-	rc = policydb_write(&policy->policydb, &fp);
-	if (rc)
-		return rc;
+/**
+ * security_read_policy_kernel - read the policy.
+ * @state: selinux_state
+ * @data: binary policy data
+ * @len: length of data in bytes
+ *
+ * Allocates kernel memory for reading SELinux policy.
+ * This function is for internal use only and should not
+ * be used for returning data to user space.
+ *
+ * This function must be called with policy_mutex held.
+ */
+int security_read_policy_kernel(struct selinux_state *state,
+				void **data, size_t *len)
+{
+	struct selinux_policy *policy;
+	int rc = 0;
 
-	*len = (unsigned long)fp.data - (unsigned long)*data;
-	return 0;
+	policy = rcu_dereference_protected(
+			state->policy, lockdep_is_held(&state->policy_mutex));
+	if (!policy) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	*len = policy->policydb.len;
+	*data = vmalloc(*len);
+	if (!*data) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
+	rc = security_read_selinux_policy(policy, *data, len);
+
+out:
+	return rc;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data
  2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
                   ` (6 preceding siblings ...)
  2020-11-01 22:26 ` [PATCH v5 7/7] selinux: measure state and hash of the policy using IMA Tushar Sugandhi
@ 2020-11-05  0:31 ` Mimi Zohar
  2020-11-12 22:18   ` Tushar Sugandhi
  7 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-05  0:31 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

Measuring "critical kernel data" is not a new infrastructure, simply a
new IMA hook.   Please update the above Subject line to "support for
measuring critical kernel data".

On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> There are several kernel subsystems that contain critical data which if
> accidentally or maliciously altered, can compromise the integrity of the
> system. Examples of such subsystems would include LSMs like SELinux, or
> AppArmor; or device-mapper targets like dm-crypt, dm-verity etc. 
> "critical data" in this context is kernel subsystem specific information
> that is stored in kernel memory. Examples of critical data could be
> kernel in-memory r/o structures, hash of the memory structures, or
> data that represents a linux kernel subsystem state.

This is a bit better, but needs to be much clearer.  Please define
"critical data", not by example, but by describing "what" critical
kernel data is.  "There are several kernel subsystems ...."  is an
example of "how" it would be used, not a definition.  Without a clear
definition it will become a dumping ground for measuring anything
anyone wants to measure.  As a result, it may be abused.

> 
> This patch set defines a new IMA hook namely CRITICAL_DATA, and a
> function ima_measure_critical_data() - to measure the critical data. 

The name of the IMA hook is ima_measure_critical_data.  This is similar
to the LSM hooks, which are prefixed with "security_".  (For a full
list of LSM hooks, refer to lsm_hook_defs.h.)

> Kernel subsystems can use this functionality, to take advantage of IMA's
> measuring and quoting abilities - thus ultimately enabling remote
> attestation for the subsystem specific information stored in the kernel
> memory.
> 
> The functionality is generic enough to measure the data of any kernel
> subsystem at run-time. To ensure that only data from supported sources
> are measured, the kernel subsystem needs to be added to a compile-time
> list of supported sources (an "allowed list of components"). IMA
> validates the source passed to ima_measure_critical_data() against this
> allowed list at run-time.

Yes, this new feature is generic, but one of the main goals of IMA is
to measure and attest to the integrity of the system, not to measure
and attest to random things.

> 
> System administrators may want to pick and choose which kernel
> subsystem information they would want to enable for measurements,
> quoting, and remote attestation. To enable that, a new IMA policy is
> introduced.

^may want to limit the critical data being measured, quoted and
attested.
^ a new IMA policy condition is defined.

> 
> This patch set also addresses the need for the kernel subsystems to
> measure their data before a custom IMA policy is loaded - by providing
> a builtin IMA policy.

^for measuring kernel critical data early, before a custom IMA policy
...

> 
> And lastly, the use of the overall functionality is demonstrated by
> measuring the kernel in-memory data for one such subsystem - SeLinux.

The purpose isn't to demonstrate the "overall functionality", but to
provide an initial caller of the new IMA hook.

thanks,

Mimi


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash
  2020-11-01 22:26 ` [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash Tushar Sugandhi
@ 2020-11-05 14:30   ` Mimi Zohar
  2020-11-12 21:47     ` Tushar Sugandhi
  2020-11-06 12:11   ` Mimi Zohar
  1 sibling, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-05 14:30 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

Please don't include the filename in the Subject line[1].   The Subject
line should be a summary phrase describing the patch.   In this case,
it is adding support for measuring the buffer data hash.

On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> process_buffer_measurement() currently only measures the input buffer.
> In case of SeLinux policy measurement, the policy being measured could
> be large (several MB). This may result in a large entry in IMA
> measurement log.

SELinux is an example of measuring large buffer data.  Please rewrite
this patch description (and the other patch descriptions in this patch
set) without using the example to describe its purpose [1].

In this case, you might say,

The original IMA buffer data measurement sizes were small (e.g. boot
command line), but new buffer data measurement use cases are a lot
larger.  Just as IMA measures the file data hash, not the file data,
IMA should similarly support measuring the buffer data hash.

> 
> Introduce a boolean parameter measure_buf_hash to support measuring
> hash of a buffer, which would be much smaller, instead of the buffer
> itself.

> To use the functionality introduced in this patch, the attestation
> client and the server changes need to go hand in hand. The
> client/kernel would know what data is being measured as-is
> (e.g. KEXEC_CMDLINE), and what data has it’s hash measured (e.g. SeLinux
> Policy). And the attestation server should verify data/hash accordingly.
> 
> Just like the data being measured in other cases, the attestation server
> will know what are possible values of the large buffers being measured.
> e.g. the possible valid SeLinux policy values that are being pushed to
> the client. The attestation server will have to maintain the hash of
> those buffer values.

Each patch in the patch set builds upon the previous one.   (Think of
it as a story, where each chapter builds upon the previous ones.)  
With rare exceptions, should patches reference subsequent patches. [2]

[1] Refer to Documentation/process/submitting-patches.rst
[2] Refer to the section "8) Commenting" in
Documentation/process/coding-style.rst

thanks,

Mimi


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash
  2020-11-01 22:26 ` [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash Tushar Sugandhi
  2020-11-05 14:30   ` Mimi Zohar
@ 2020-11-06 12:11   ` Mimi Zohar
  2020-11-12 21:48     ` Tushar Sugandhi
  1 sibling, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-06 12:11 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

Below inline are a few additional comments.

> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index ae5da9f3339d..4485d87c0aa5 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -787,12 +787,15 @@ int ima_post_load_data(char *buf, loff_t size,
>   * @func: IMA hook
>   * @pcr: pcr to extend the measurement
>   * @func_data: private data specific to @func, can be NULL.
> + * @measure_buf_hash: if set to true - will measure hash of the buf,
> + *                    instead of buf
>   *
>   * Based on policy, the buffer is measured into the ima log.

Both the brief and longer function descriptions need to be updated, as
well as the last argument description.  The last argument should be
limited to "measure buffer hash".  How it is used could be included in
the longer function description.  The longer function description would
include adding the buffer data or the buffer data hash to the IMA
measurement list and extending the PCR.  

For example, 
process_buffer_measurement - measure the buffer data or the buffer data
hash


>   */
>  void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>  				const char *eventname, enum ima_hooks func,
> -				int pcr, const char *func_data)
> +				int pcr, const char *func_data,
> +				bool measure_buf_hash)
>  {
>  	int ret = 0;
>  	const char *audit_cause = "ENOMEM";
> @@ -807,6 +810,8 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>  		struct ima_digest_data hdr;
>  		char digest[IMA_MAX_DIGEST_SIZE];
>  	} hash = {};
> +	char digest_hash[IMA_MAX_DIGEST_SIZE];
> +	int hash_len = hash_digest_size[ima_hash_algo];
>  	int violation = 0;
>  	int action = 0;
>  	u32 secid;
> @@ -855,6 +860,21 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>  		goto out;
>  	}
>  
> +	if (measure_buf_hash) {
> +		memcpy(digest_hash, hash.hdr.digest, hash_len);

Instead of digest_hash and hash_len, consider naming the variables
buf_hash and buf_hashlen.

> +
> +		ret = ima_calc_buffer_hash(digest_hash,
> +					   hash_len,
> +					   iint.ima_hash);

There's no need for each variable to be on a separate line.

thanks,

Mimi

> +		if (ret < 0) {
> +			audit_cause = "measure_buf_hash_error";
> +			goto out;
> +		}
> +
> +		event_data.buf = digest_hash;
> +		event_data.buf_len = hash_len;
> +	}
> +
>  	ret = ima_alloc_init_template(&event_data, &entry, template);
>  	if (ret < 0) {
>  		audit_cause = "alloc_entry";


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 3/7] IMA: add hook to measure critical data
  2020-11-01 22:26 ` [PATCH v5 3/7] IMA: add hook to measure critical data Tushar Sugandhi
@ 2020-11-06 13:24   ` Mimi Zohar
  2020-11-12 21:57     ` Tushar Sugandhi
  0 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-06 13:24 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> Currently, IMA does not provide a generic function for kernel subsystems
> to measure their critical data. Examples of critical data in this context
> could be kernel in-memory r/o structures, hash of the memory structures,
> or data that represents a linux kernel subsystem state change. The 
> critical data, if accidentally or maliciously altered, can compromise
> the integrity of the system.

Start out with what IMA does do (e.g. measures files and more recently
buffer data).  Afterwards continue with kernel integrity critical data
should also be measured.  Please include a definition of kernel
integrity critical data here, as well as in the cover letter.

> 
> A generic function provided by IMA to measure critical data would enable
> various subsystems with easier and faster on-boarding to use IMA
> infrastructure and would also avoid code duplication.

By definition LSM and IMA hooks are generic with callers in appropriate
places in the kernel.   This paragraph is redundant.

> 
> Add a new IMA func CRITICAL_DATA and a corresponding IMA hook
> ima_measure_critical_data() to support measuring critical data for 
> various kernel subsystems. 

Instead of using the word "add", it would be more appropriate to use
the word "define".   Define a new IMA hook named
ima_measure_critical_data to measure kernel integrity critical data.  
Please also update the Subject line as well.  "ima: define an IMA hook
to measure kernel integrity critical data".

> 
> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
> ---
> 
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 4485d87c0aa5..6e1b11dcba53 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -921,6 +921,44 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
>  	fdput(f);
>  }
>  
> +/**
> + * ima_measure_critical_data - measure kernel subsystem data
> + * critical to integrity of the kernel

Please change this to "measure kernel integrity critical data".

> + * @event_data_source: name of the data source being measured;
> + * typically it should be the name of the kernel subsystem that is sending
> + * the data for measurement

Including "data_source" here isn't quite right.  "data source" should
only be added in the first patch which uses it, not here.   When adding
it please shorten the field description to "kernel data source".   The
longer explanation can be included in the longer function description.

> + * @event_name: name of an event from the kernel subsystem that is sending
> + * the data for measurement

As this is being passed to process_buffer_measurement(), this should be
the same or similar to the existing definition.

> + * @buf: pointer to buffer containing data to measure
> + * @buf_len: length of buffer(in bytes)
> + * @measure_buf_hash: if set to true - will measure hash of the buf,
> + *                    instead of buf

 kernel doc requires a single line.  In this case, please shorten the
argument definition to "measure buffer data or buffer data hash".   The
details can be included in the longer function description.

> + *
> + * A given kernel subsystem (event_data_source) may send
> + * data (buf) to be measured when the data or the subsystem state changes.
> + * The state/data change can be described by event_name.
> + * Examples of critical data (buf) could be kernel in-memory r/o structures,
> + * hash of the memory structures, or data that represents subsystem
> + * state change.
> + * measure_buf_hash can be used to save space, if the data being measured
> + * is too large.
> + * The data (buf) can only be measured, not appraised.
> + */

Please remove this longer function description, replacing it something
more appropriate.  The subsequent patch that introduces the "data
source" parameter would expand the description.

thanks,

Mimi

> +void ima_measure_critical_data(const char *event_data_source,
> +			       const char *event_name,
> +			       const void *buf, int buf_len,
> +			       bool measure_buf_hash)
> +{
> +	if (!event_name || !event_data_source || !buf || !buf_len) {
> +		pr_err("Invalid arguments passed to %s().\n", __func__);
> +		return;
> +	}
> +
> +	process_buffer_measurement(NULL, buf, buf_len, event_name,
> +				   CRITICAL_DATA, 0, event_data_source,
> +				   measure_buf_hash);
> +}
> +
>  static int __init init_ima(void)
>  {
>  	int error;


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 4/7] IMA: add policy to measure critical data
  2020-11-01 22:26 ` [PATCH v5 4/7] IMA: add policy " Tushar Sugandhi
@ 2020-11-06 13:43   ` Mimi Zohar
  2020-11-12 22:02     ` Tushar Sugandhi
  0 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-06 13:43 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> System administrators should be able to choose which kernel subsystems
> they want to measure the critical data for. To enable that, an IMA policy
> option to choose specific kernel subsystems is needed. This policy option
> would constrain the measurement of the critical data to the given kernel
> subsystems.

Measuring critical data should not be dependent on the source of the
critical data.   This patch needs to be split up.  The "data sources"
should be move to it's own separate patch.  This patch should be
limited to adding the policy code needed for measuring criticial data. 
Limiting critical data sources should be the last patch in this series.

thanks,

Mimi

> 
> Add a new IMA policy option - "data_sources:=" to the IMA func 
> CRITICAL_DATA to allow measurement of various kernel subsystems. This
> policy option would enable the system administrators to limit the
> measurement to the subsystems listed in "data_sources:=", if the 
> subsystem measures its data by calling ima_measure_critical_data().
> 
> Limit the measurement to the subsystems that are specified in the IMA
> policy - CRITICAL_DATA+"data_sources:=". If "data_sources:=" is not
> provided with the func CRITICAL_DATA, measure the data from all the
> supported kernel subsystems.
> 
> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement
  2020-11-01 22:26 ` [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement Tushar Sugandhi
@ 2020-11-06 14:01   ` Mimi Zohar
  2020-11-12 22:09     ` Tushar Sugandhi
  0 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-06 14:01 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> Currently, IMA does not restrict random data sources from measuring
> their data using ima_measure_critical_data(). Any kernel data source can
> call the function, and it's data will get measured as long as the input
> event_data_source is part of the IMA policy - CRITICAL_DATA+data_sources.
> 
> To ensure that only data from supported sources are measured, the kernel
> subsystem name needs to be added to a compile-time list of supported
> sources (an "allowed list of components"). IMA then validates the input
> parameter - "event_data_source" passed to ima_measure_critical_data()
> against this allowed list at run-time.
> 
> This compile-time list must be updated when kernel subsystems are
> updated to measure their data using IMA.
> 
> Provide an infrastructure for kernel data sources to be added to
> IMA's supported data sources list at compile-time. Update
> ima_measure_critical_data() to validate, at run-time, that the data
> source is supported before measuring the data coming from that source.

For those interested in limiting which critical data to measure, the
"data sources" IMA policy rule option already does that.   Why is this
needed?

thanks,

Mimi


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules
  2020-11-01 22:26 ` [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules Tushar Sugandhi
@ 2020-11-06 15:24   ` Mimi Zohar
  2020-11-06 15:37     ` Lakshmi Ramasubramanian
  0 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-06 15:24 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Lakshmi, Tushar,

This patch defines a new critical_data builtin policy.  Please update
the Subject line.

On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> From: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> 
> The IMA hook to measure kernel critical data, namely
> ima_measure_critical_data(), could be called before a custom IMA policy
> is loaded. For example, SELinux calls ima_measure_critical_data() to
> measure its state and policy when they are initialized. This occurs
> before a custom IMA policy is loaded, and hence IMA hook will not
> measure the data. A built-in policy is therefore needed to measure
> critical data provided by callers before a custom IMA policy is loaded.

^Define a new critical data builtin policy to allow measuring early
kernel integrity critical data before a custom IMA policy is loaded.

Either remove the references to SELinux or move this patch after the
subsequent patch which measures SELinux critical data.

> 
> Add CRITICAL_DATA to built-in IMA rules if the kernel command line
> contains "ima_policy=critical_data". Set the IMA template for this rule
> to "ima-buf" since ima_measure_critical_data() measures a buffer.
> 
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>

> ---
>  security/integrity/ima/ima_policy.c | 32 +++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index ec99e0bb6c6f..dc8fe969d3fe 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c

> @@ -875,6 +884,29 @@ void __init ima_init_policy(void)
>  			  ARRAY_SIZE(default_appraise_rules),
>  			  IMA_DEFAULT_POLICY);
>  
> +	if (ima_use_critical_data) {
> +		template = lookup_template_desc("ima-buf");
> +		if (!template) {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +
> +		ret = template_desc_init_fields(template->fmt,
> +						&(template->fields),
> +						&(template->num_fields));

The default IMA template when measuring buffer data is "ima_buf".   Is
there a reason for allocating and initializing it here and not
deferring it until process_buffer_measurement()?

thanks,

Mimi

> +		if (ret)
> +			goto out;
> +
> +		critical_data_rules[0].template = template;
> +		add_rules(critical_data_rules,
> +			  ARRAY_SIZE(critical_data_rules),
> +			  IMA_DEFAULT_POLICY);
> +	}
> +
> +out:
> +	if (ret)
> +		pr_err("%s failed, result: %d\n", __func__, ret);
> +
>  	ima_update_policy_flag();
>  }
>  



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules
  2020-11-06 15:24   ` Mimi Zohar
@ 2020-11-06 15:37     ` Lakshmi Ramasubramanian
  2020-11-06 23:51       ` Lakshmi Ramasubramanian
  0 siblings, 1 reply; 31+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-11-06 15:37 UTC (permalink / raw)
  To: Mimi Zohar, Tushar Sugandhi, stephen.smalley.work, casey, agk,
	snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

On 11/6/20 7:24 AM, Mimi Zohar wrote:

Hi Mimi,

Thanks for reviewing the patches.

> Hi Lakshmi, Tushar,
> 
> This patch defines a new critical_data builtin policy.  Please update
> the Subject line.
> 
> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>> From: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
>>
>> The IMA hook to measure kernel critical data, namely
>> ima_measure_critical_data(), could be called before a custom IMA policy
>> is loaded. For example, SELinux calls ima_measure_critical_data() to
>> measure its state and policy when they are initialized. This occurs
>> before a custom IMA policy is loaded, and hence IMA hook will not
>> measure the data. A built-in policy is therefore needed to measure
>> critical data provided by callers before a custom IMA policy is loaded.
> 
> ^Define a new critical data builtin policy to allow measuring early
> kernel integrity critical data before a custom IMA policy is loaded.

I will add the above line in the patch description.

> 
> Either remove the references to SELinux or move this patch after the
> subsequent patch which measures SELinux critical data.

I will remove the reference to SELinux.
I think it would be better to have this patch before the SELinux 
measurement patch.

> 
>>
>> Add CRITICAL_DATA to built-in IMA rules if the kernel command line
>> contains "ima_policy=critical_data". Set the IMA template for this rule
>> to "ima-buf" since ima_measure_critical_data() measures a buffer.
>>
>> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> 
>> ---
>>   security/integrity/ima/ima_policy.c | 32 +++++++++++++++++++++++++++++
>>   1 file changed, 32 insertions(+)
>>
>> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
>> index ec99e0bb6c6f..dc8fe969d3fe 100644
>> --- a/security/integrity/ima/ima_policy.c
>> +++ b/security/integrity/ima/ima_policy.c
> 
>> @@ -875,6 +884,29 @@ void __init ima_init_policy(void)
>>   			  ARRAY_SIZE(default_appraise_rules),
>>   			  IMA_DEFAULT_POLICY);
>>   
>> +	if (ima_use_critical_data) {
>> +		template = lookup_template_desc("ima-buf");
>> +		if (!template) {
>> +			ret = -EINVAL;
>> +			goto out;
>> +		}
>> +
>> +		ret = template_desc_init_fields(template->fmt,
>> +						&(template->fields),
>> +						&(template->num_fields));
> 
> The default IMA template when measuring buffer data is "ima_buf".   Is
> there a reason for allocating and initializing it here and not
> deferring it until process_buffer_measurement()?
> 

You are right - good catch.
I will remove the above and validate.

thanks,
  -lakshmi

> 
>> +		if (ret)
>> +			goto out;
>> +
>> +		critical_data_rules[0].template = template;
>> +		add_rules(critical_data_rules,
>> +			  ARRAY_SIZE(critical_data_rules),
>> +			  IMA_DEFAULT_POLICY);
>> +	}
>> +
>> +out:
>> +	if (ret)
>> +		pr_err("%s failed, result: %d\n", __func__, ret);
>> +
>>   	ima_update_policy_flag();
>>   }
>>   
> 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 7/7] selinux: measure state and hash of the policy using IMA
  2020-11-01 22:26 ` [PATCH v5 7/7] selinux: measure state and hash of the policy using IMA Tushar Sugandhi
@ 2020-11-06 15:47   ` Mimi Zohar
  0 siblings, 0 replies; 31+ messages in thread
From: Mimi Zohar @ 2020-11-06 15:47 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Lakshmi, Tushar,

On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> From: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> 
> Critical data structures of security modules are currently not measured.

Right, this patch set adds support for measuring kernel integrity
critical data.  Why is this statement needed?

> Therefore an attestation service, for instance, would not be able to
> attest whether the security modules are always operating with the policies
> and configurations that the system administrator had setup. The policies
> and configurations for the security modules could be tampered by rogue
> user mode agents or modified through some inadvertent actions on
> the system. Measuring such critical data would enable an attestation
> service to reliably assess the security configuration of the system.

Please rewrite this paragraph from the perspective of measuring files
and other buffer data is not sufficient, providing an explanation why
it is isn't sufficient.

This is a rather large patch.   I'm surprised that it isn't broken up
into two patches, one that measures SELinux policy data and another
which measures the state, but that is Stephen's and Paul's call.

Mimi


> SELinux configuration and policy are some of the critical data for this
> security module that need to be measured. This measurement can be used
> by an attestation service, for instance, to verify if the configurations
> and policies have been setup correctly and that they haven't been
> tampered at run-time.
> 
> Measure SELinux configurations, policy capabilities settings, and
> the hash of the loaded policy by calling the IMA hook
> ima_measure_critical_data(). Since the size of the loaded policy can
> be large (several MB), measure the hash of the policy instead of
> the entire policy to avoid bloating the IMA log entry.
> 
> Add "selinux" to the list of supported data sources maintained by IMA
> to enable measuring SELinux data.
> 
> To enable SELinux data measurement, the following steps are required:
> 
> 1, Add "ima_policy=critical_data" to the kernel command line arguments
>    to enable measuring SELinux data at boot time.
> For example,
>   BOOT_IMAGE=/boot/vmlinuz-5.10.0-rc1+ root=UUID=fd643309-a5d2-4ed3-b10d-3c579a5fab2f ro nomodeset security=selinux ima_policy=critical_data
> 
> 2, Add the following rule to /etc/ima/ima-policy
>    measure func=CRITICAL_DATA data_sources=selinux template=ima-buf
> 
> Sample measurement of SELinux state and hash of the policy:
> 
> 10 e32e...5ac3 ima-buf sha256:86e8...4594 selinux-state-1595389364:287899386 696e697469616c697a65643d313b656e61626c65643d313b656e666f7263696e673d303b636865636b72657170726f743d313b6e6574776f726b5f706565725f636f6e74726f6c733d313b6f70656e5f7065726d733d313b657874656e6465645f736f636b65745f636c6173733d313b616c776179735f636865636b5f6e6574776f726b3d303b6367726f75705f7365636c6162656c3d313b6e6e705f6e6f737569645f7472616e736974696f6e3d313b67656e66735f7365636c6162656c5f73796d6c696e6b733d303
> 10 9e81...0857 ima-buf sha256:4941...68fc selinux-policy-hash-1597335667:462051628 8d1d...1834
> 
> To verify the measurement check the following:
> 
> Execute the following command to extract the measured data
> from the IMA log for SELinux configuration (selinux-state).
> 
>   grep "selinux-state" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | tail -1 | cut -d' ' -f 6 | xxd -r -p
> 
> The output should be the list of key-value pairs. For example,
>  initialized=1;enabled=1;enforcing=0;checkreqprot=1;network_peer_controls=1;open_perms=1;extended_socket_class=1;always_check_network=0;cgroup_seclabel=1;nnp_nosuid_transition=1;genfs_seclabel_symlinks=0;
> 
> To verify the measured data with the current SELinux state:
> 
>  => enabled should be set to 1 if /sys/fs/selinux folder exists,
>     0 otherwise
> 
> For other entries, compare the integer value in the files
>  => /sys/fs/selinux/enforce
>  => /sys/fs/selinux/checkreqprot
> And, each of the policy capabilities files under
>  => /sys/fs/selinux/policy_capabilities
> 
> Note that the actual verification would be against an expected state
> and done on a system other than the measured system, typically
> requiring "initialized=1; enabled=1;enforcing=1;checkreqprot=0;" for
> a secure state and then whatever policy capabilities are actually set
> in the expected policy (which can be extracted from the policy itself
> via seinfo, for example).
> 
> For selinux-policy-hash, the hash of SELinux policy is included
> in the IMA log entry.
> 
> To verify the measured data with the current SELinux policy run
> the following commands and verify the output hash values match.
> 
>   sha256sum /sys/fs/selinux/policy | cut -d' ' -f 1
> 
>   grep "selinux-policy-hash" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | tail -1 | cut -d' ' -f 6
> 
> Note that the actual verification of SELinux policy would require loading
> the expected policy into an identical kernel on a pristine/known-safe
> system and run the sha256sum /sys/kernel/selinux/policy there to get
> the expected hash.
> 
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>

Please reverse the order of the tags.

thanks,

Mimi


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules
  2020-11-06 15:37     ` Lakshmi Ramasubramanian
@ 2020-11-06 23:51       ` Lakshmi Ramasubramanian
  2020-11-08 15:46         ` Mimi Zohar
  0 siblings, 1 reply; 31+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-11-06 23:51 UTC (permalink / raw)
  To: Mimi Zohar, Tushar Sugandhi, stephen.smalley.work, casey, agk,
	snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

On 11/6/20 7:37 AM, Lakshmi Ramasubramanian wrote:

Hi Mimi,

> 
>> Hi Lakshmi, Tushar,
>>
>> This patch defines a new critical_data builtin policy.  Please update
>> the Subject line.
>>
>> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>>> From: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
>>>
>>> The IMA hook to measure kernel critical data, namely
>>> ima_measure_critical_data(), could be called before a custom IMA policy
>>> is loaded. For example, SELinux calls ima_measure_critical_data() to
>>> measure its state and policy when they are initialized. This occurs
>>> before a custom IMA policy is loaded, and hence IMA hook will not
>>> measure the data. A built-in policy is therefore needed to measure
>>> critical data provided by callers before a custom IMA policy is loaded.
>>
>> ^Define a new critical data builtin policy to allow measuring early
>> kernel integrity critical data before a custom IMA policy is loaded.
> 
> I will add the above line in the patch description.
> 
>>
>> Either remove the references to SELinux or move this patch after the
>> subsequent patch which measures SELinux critical data.
> 
> I will remove the reference to SELinux.
> I think it would be better to have this patch before the SELinux 
> measurement patch.
> 
>>
>>>
>>> Add CRITICAL_DATA to built-in IMA rules if the kernel command line
>>> contains "ima_policy=critical_data". Set the IMA template for this rule
>>> to "ima-buf" since ima_measure_critical_data() measures a buffer.
>>>
>>> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
>>
>>> ---
>>>   security/integrity/ima/ima_policy.c | 32 +++++++++++++++++++++++++++++
>>>   1 file changed, 32 insertions(+)
>>>
>>> diff --git a/security/integrity/ima/ima_policy.c 
>>> b/security/integrity/ima/ima_policy.c
>>> index ec99e0bb6c6f..dc8fe969d3fe 100644
>>> --- a/security/integrity/ima/ima_policy.c
>>> +++ b/security/integrity/ima/ima_policy.c
>>
>>> @@ -875,6 +884,29 @@ void __init ima_init_policy(void)
>>>                 ARRAY_SIZE(default_appraise_rules),
>>>                 IMA_DEFAULT_POLICY);
>>> +    if (ima_use_critical_data) {
>>> +        template = lookup_template_desc("ima-buf");
>>> +        if (!template) {
>>> +            ret = -EINVAL;
>>> +            goto out;
>>> +        }
>>> +
>>> +        ret = template_desc_init_fields(template->fmt,
>>> +                        &(template->fields),
>>> +                        &(template->num_fields));
>>
>> The default IMA template when measuring buffer data is "ima_buf".   Is
>> there a reason for allocating and initializing it here and not
>> deferring it until process_buffer_measurement()?
>>
> 
> You are right - good catch.
> I will remove the above and validate.
> 

process_buffer_measurement() allocates and initializes "ima-buf" 
template only when the parameter "func" is NONE. Currently, only 
ima_check_blacklist() passes NONE for func when calling 
process_buffer_measurement().

If "func" is anything other than NONE, ima_match_policy() picks
the default IMA template if the IMA policy rule does not specify a template.

We need to add "ima-buf" in the built-in policy for critical_data so 
that the default template is not used for buffer measurement.

Please let me know if I am missing something.

thanks,
  -lakshmi

>>
>>> +        if (ret)
>>> +            goto out;
>>> +
>>> +        critical_data_rules[0].template = template;
>>> +        add_rules(critical_data_rules,
>>> +              ARRAY_SIZE(critical_data_rules),
>>> +              IMA_DEFAULT_POLICY);
>>> +    }
>>> +
>>> +out:
>>> +    if (ret)
>>> +        pr_err("%s failed, result: %d\n", __func__, ret);
>>> +
>>>       ima_update_policy_flag();
>>>   }
>>
> 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules
  2020-11-06 23:51       ` Lakshmi Ramasubramanian
@ 2020-11-08 15:46         ` Mimi Zohar
  2020-11-09 17:24           ` Lakshmi Ramasubramanian
  0 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-08 15:46 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, Tushar Sugandhi, stephen.smalley.work,
	casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Lakshmi,

On Fri, 2020-11-06 at 15:51 -0800, Lakshmi Ramasubramanian wrote:
> 
> >>> diff --git a/security/integrity/ima/ima_policy.c 
> >>> b/security/integrity/ima/ima_policy.c
> >>> index ec99e0bb6c6f..dc8fe969d3fe 100644
> >>> --- a/security/integrity/ima/ima_policy.c
> >>> +++ b/security/integrity/ima/ima_policy.c
> >>
> >>> @@ -875,6 +884,29 @@ void __init ima_init_policy(void)
> >>>                 ARRAY_SIZE(default_appraise_rules),
> >>>                 IMA_DEFAULT_POLICY);
> >>> +    if (ima_use_critical_data) {
> >>> +        template = lookup_template_desc("ima-buf");
> >>> +        if (!template) {
> >>> +            ret = -EINVAL;
> >>> +            goto out;
> >>> +        }
> >>> +
> >>> +        ret = template_desc_init_fields(template->fmt,
> >>> +                        &(template->fields),
> >>> +                        &(template->num_fields));
> >>
> >> The default IMA template when measuring buffer data is "ima_buf".   Is
> >> there a reason for allocating and initializing it here and not
> >> deferring it until process_buffer_measurement()?
> >>
> > 
> > You are right - good catch.
> > I will remove the above and validate.
> > 
> 
> process_buffer_measurement() allocates and initializes "ima-buf" 
> template only when the parameter "func" is NONE. Currently, only 
> ima_check_blacklist() passes NONE for func when calling 
> process_buffer_measurement().
> 
> If "func" is anything other than NONE, ima_match_policy() picks
> the default IMA template if the IMA policy rule does not specify a template.
> 
> We need to add "ima-buf" in the built-in policy for critical_data so 
> that the default template is not used for buffer measurement.
> 
> Please let me know if I am missing something.
> 

Let's explain a bit further what is happening and why.   As you said
ima_get_action() returns the template format, which may be the default
IMA template or the specific IMA policy rule template format.  This
works properly for both the arch specific and custom policies, but not
for builtin policies, because the policy rules may contain a rule
specific .template field.   When the rules don't contain a rule
specific template field, they default to the IMA default template.  In
the case of builtin policies, the policy rules cannot contain the
.template field.

The default template field for process_buffer_measurement() should
always be "ima-buf", not the default IMA template format.   Let's fix
this prior to this patch.

Probably something like this:
- In addition to initializing the default IMA template, initialize the
"ima-buf" template.  Maybe something similiar to
ima_template_desc_current().
- Set the default in process_buffer_measurement() to "ima-buf", before
calling ima_get_action().
- modify ima_match_policy() so that the default policy isn't reset when
already specified.

thanks,

Mimi


> >>
> >>> +        if (ret)
> >>> +            goto out;
> >>> +
> >>> +        critical_data_rules[0].template = template;
> >>> +        add_rules(critical_data_rules,
> >>> +              ARRAY_SIZE(critical_data_rules),
> >>> +              IMA_DEFAULT_POLICY);
> >>> +    }
> >>> +
> >>> +out:
> >>> +    if (ret)
> >>> +        pr_err("%s failed, result: %d\n", __func__, ret);
> >>> +
> >>>       ima_update_policy_flag();
> >>>   }
> >>
> > 
> 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules
  2020-11-08 15:46         ` Mimi Zohar
@ 2020-11-09 17:24           ` Lakshmi Ramasubramanian
  0 siblings, 0 replies; 31+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-11-09 17:24 UTC (permalink / raw)
  To: Mimi Zohar, Tushar Sugandhi, stephen.smalley.work, casey, agk,
	snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

On 11/8/20 7:46 AM, Mimi Zohar wrote:
> Hi Lakshmi,
> 
> On Fri, 2020-11-06 at 15:51 -0800, Lakshmi Ramasubramanian wrote:
>>
>>>>> diff --git a/security/integrity/ima/ima_policy.c
>>>>> b/security/integrity/ima/ima_policy.c
>>>>> index ec99e0bb6c6f..dc8fe969d3fe 100644
>>>>> --- a/security/integrity/ima/ima_policy.c
>>>>> +++ b/security/integrity/ima/ima_policy.c
>>>>
>>>>> @@ -875,6 +884,29 @@ void __init ima_init_policy(void)
>>>>>                  ARRAY_SIZE(default_appraise_rules),
>>>>>                  IMA_DEFAULT_POLICY);
>>>>> +    if (ima_use_critical_data) {
>>>>> +        template = lookup_template_desc("ima-buf");
>>>>> +        if (!template) {
>>>>> +            ret = -EINVAL;
>>>>> +            goto out;
>>>>> +        }
>>>>> +
>>>>> +        ret = template_desc_init_fields(template->fmt,
>>>>> +                        &(template->fields),
>>>>> +                        &(template->num_fields));
>>>>
>>>> The default IMA template when measuring buffer data is "ima_buf".   Is
>>>> there a reason for allocating and initializing it here and not
>>>> deferring it until process_buffer_measurement()?
>>>>
>>>
>>> You are right - good catch.
>>> I will remove the above and validate.
>>>
>>
>> process_buffer_measurement() allocates and initializes "ima-buf"
>> template only when the parameter "func" is NONE. Currently, only
>> ima_check_blacklist() passes NONE for func when calling
>> process_buffer_measurement().
>>
>> If "func" is anything other than NONE, ima_match_policy() picks
>> the default IMA template if the IMA policy rule does not specify a template.
>>
>> We need to add "ima-buf" in the built-in policy for critical_data so
>> that the default template is not used for buffer measurement.
>>
>> Please let me know if I am missing something.
>>
> 
> Let's explain a bit further what is happening and why.   As you said
> ima_get_action() returns the template format, which may be the default
> IMA template or the specific IMA policy rule template format.  This
> works properly for both the arch specific and custom policies, but not
> for builtin policies, because the policy rules may contain a rule
> specific .template field.   When the rules don't contain a rule
> specific template field, they default to the IMA default template.  In
> the case of builtin policies, the policy rules cannot contain the
> .template field.
> 
> The default template field for process_buffer_measurement() should
> always be "ima-buf", not the default IMA template format.   Let's fix
> this prior to this patch.
> 
> Probably something like this:
> - In addition to initializing the default IMA template, initialize the
> "ima-buf" template.  Maybe something similiar to
> ima_template_desc_current().
> - Set the default in process_buffer_measurement() to "ima-buf", before
> calling ima_get_action().
> - modify ima_match_policy() so that the default policy isn't reset when
> already specified.
> 

Sure Mimi - I will try this out and update.

thanks,
  -lakshmi

> 
> 
>>>>
>>>>> +        if (ret)
>>>>> +            goto out;
>>>>> +
>>>>> +        critical_data_rules[0].template = template;
>>>>> +        add_rules(critical_data_rules,
>>>>> +              ARRAY_SIZE(critical_data_rules),
>>>>> +              IMA_DEFAULT_POLICY);
>>>>> +    }
>>>>> +
>>>>> +out:
>>>>> +    if (ret)
>>>>> +        pr_err("%s failed, result: %d\n", __func__, ret);
>>>>> +
>>>>>        ima_update_policy_flag();
>>>>>    }
>>>>
>>>
>>


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash
  2020-11-05 14:30   ` Mimi Zohar
@ 2020-11-12 21:47     ` Tushar Sugandhi
  2020-11-12 22:19       ` Mimi Zohar
  0 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-12 21:47 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hello Mimi,

On 2020-11-05 6:30 a.m., Mimi Zohar wrote:
> Hi Tushar,
> 
> Please don't include the filename in the Subject line[1].   The Subject
> line should be a summary phrase describing the patch.   In this case,
> it is adding support for measuring the buffer data hash.
> 
Thanks. Will update the subject line accordingly.

> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>> process_buffer_measurement() currently only measures the input buffer.
>> In case of SeLinux policy measurement, the policy being measured could
>> be large (several MB). This may result in a large entry in IMA
>> measurement log.
> 
> SELinux is an example of measuring large buffer data.  Please rewrite
> this patch description (and the other patch descriptions in this patch
> set) without using the example to describe its purpose [1].
> 
> In this case, you might say,
> 
> The original IMA buffer data measurement sizes were small (e.g. boot
> command line), but new buffer data measurement use cases are a lot
> larger.  Just as IMA measures the file data hash, not the file data,
> IMA should similarly support measuring the buffer data hash.
> 
Sure. Thanks a lot for giving an example wording for us. Will update.
>>
>> Introduce a boolean parameter measure_buf_hash to support measuring
>> hash of a buffer, which would be much smaller, instead of the buffer
>> itself.
> 
>> To use the functionality introduced in this patch, the attestation
>> client and the server changes need to go hand in hand. The
>> client/kernel would know what data is being measured as-is
>> (e.g. KEXEC_CMDLINE), and what data has it’s hash measured (e.g. SeLinux
>> Policy). And the attestation server should verify data/hash accordingly.
>>
>> Just like the data being measured in other cases, the attestation server
>> will know what are possible values of the large buffers being measured.
>> e.g. the possible valid SeLinux policy values that are being pushed to
>> the client. The attestation server will have to maintain the hash of
>> those buffer values.
> 
> Each patch in the patch set builds upon the previous one.   (Think of
> it as a story, where each chapter builds upon the previous ones.)
> With rare exceptions, should patches reference subsequent patches. [2]
> 
> [1] Refer to Documentation/process/submitting-patches.rst
> [2] Refer to the section "8) Commenting" in
> Documentation/process/coding-style.rst
> 
> thanks,
> 
> Mimi
> 
I am not sure if you have any concerns about the last two paragraphs.
The description about the attestation client and server (the last two
paragraphs) was added for information/clarification purpose only, as per
your feedback on previous iterations. The subsequent patches don’t have
any code pertaining to attestation client/server.

*Question*
Maybe the last two paragraphs are confusing/redundant. Could you please
let me know if I should remove the above two paragraphs altogether? 
(starting with “To use the functionality introduced in this patch ...”)

If we decide to keep the paragraphs, I will remove the specific examples
(KEXEC_CMDLINE, SeLinux etc.) as you mentioned elsewhere.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash
  2020-11-06 12:11   ` Mimi Zohar
@ 2020-11-12 21:48     ` Tushar Sugandhi
  0 siblings, 0 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-12 21:48 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel



On 2020-11-06 4:11 a.m., Mimi Zohar wrote:
> Hi Tushar,
> 
> Below inline are a few additional comments.
> 
>> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
>> index ae5da9f3339d..4485d87c0aa5 100644
>> --- a/security/integrity/ima/ima_main.c
>> +++ b/security/integrity/ima/ima_main.c
>> @@ -787,12 +787,15 @@ int ima_post_load_data(char *buf, loff_t size,
>>    * @func: IMA hook
>>    * @pcr: pcr to extend the measurement
>>    * @func_data: private data specific to @func, can be NULL.
>> + * @measure_buf_hash: if set to true - will measure hash of the buf,
>> + *                    instead of buf
>>    *
>>    * Based on policy, the buffer is measured into the ima log.
> 
> Both the brief and longer function descriptions need to be updated, as
> well as the last argument description.  The last argument should be
> limited to "measure buffer hash".  How it is used could be included in
> the longer function description.  The longer function description would
> include adding the buffer data or the buffer data hash to the IMA
> measurement list and extending the PCR.
> 
> For example,
> process_buffer_measurement - measure the buffer data or the buffer data
> hash
> 
Thanks Mimi. Will update the brief and longer descriptions accordingly.
> 
>>    */
>>   void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>>   				const char *eventname, enum ima_hooks func,
>> -				int pcr, const char *func_data)
>> +				int pcr, const char *func_data,
>> +				bool measure_buf_hash)
>>   {
>>   	int ret = 0;
>>   	const char *audit_cause = "ENOMEM";
>> @@ -807,6 +810,8 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>>   		struct ima_digest_data hdr;
>>   		char digest[IMA_MAX_DIGEST_SIZE];
>>   	} hash = {};
>> +	char digest_hash[IMA_MAX_DIGEST_SIZE];
>> +	int hash_len = hash_digest_size[ima_hash_algo];
>>   	int violation = 0;
>>   	int action = 0;
>>   	u32 secid;
>> @@ -855,6 +860,21 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>>   		goto out;
>>   	}
>>   
>> +	if (measure_buf_hash) {
>> +		memcpy(digest_hash, hash.hdr.digest, hash_len);
> 
> Instead of digest_hash and hash_len, consider naming the variables
> buf_hash and buf_hashlen.
> 
Thanks. Will do.
>> +
>> +		ret = ima_calc_buffer_hash(digest_hash,
>> +					   hash_len,
>> +					   iint.ima_hash);
> 
> There's no need for each variable to be on a separate line.
> 
Thanks, will fix.
~Tushar

> thanks,
> 
> Mimi
> 
>> +		if (ret < 0) {
>> +			audit_cause = "measure_buf_hash_error";
>> +			goto out;
>> +		}
>> +
>> +		event_data.buf = digest_hash;
>> +		event_data.buf_len = hash_len;
>> +	}
>> +
>>   	ret = ima_alloc_init_template(&event_data, &entry, template);
>>   	if (ret < 0) {
>>   		audit_cause = "alloc_entry";

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 3/7] IMA: add hook to measure critical data
  2020-11-06 13:24   ` Mimi Zohar
@ 2020-11-12 21:57     ` Tushar Sugandhi
  2020-11-12 23:56       ` Mimi Zohar
  0 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-12 21:57 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel



On 2020-11-06 5:24 a.m., Mimi Zohar wrote:
> Hi Tushar,
> 
> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>> Currently, IMA does not provide a generic function for kernel subsystems
>> to measure their critical data. Examples of critical data in this context
>> could be kernel in-memory r/o structures, hash of the memory structures,
>> or data that represents a linux kernel subsystem state change. The
>> critical data, if accidentally or maliciously altered, can compromise
>> the integrity of the system.
> 
> Start out with what IMA does do (e.g. measures files and more recently
> buffer data).  Afterwards continue with kernel integrity critical data
> should also be measured.  Please include a definition of kernel
> integrity critical data here, as well as in the cover letter.
> 
Yes, will do. I will also describe what kernel integrity critical data
is – by providing a definition, and not by example -  as you suggested.
(here and in the cover letter)

>>
>> A generic function provided by IMA to measure critical data would enable
>> various subsystems with easier and faster on-boarding to use IMA
>> infrastructure and would also avoid code duplication.
> 
> By definition LSM and IMA hooks are generic with callers in appropriate
> places in the kernel.   This paragraph is redundant.
> 
Sounds good. I will remove this paragraph.
>>
>> Add a new IMA func CRITICAL_DATA and a corresponding IMA hook
>> ima_measure_critical_data() to support measuring critical data for
>> various kernel subsystems.
> 
> Instead of using the word "add", it would be more appropriate to use
> the word "define".   Define a new IMA hook named
> ima_measure_critical_data to measure kernel integrity critical data.
> Please also update the Subject line as well.  "ima: define an IMA hook
> to measure kernel integrity critical data".
> 
Sounds good. Will do.
>>
>> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
>> ---
>>
>> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
>> index 4485d87c0aa5..6e1b11dcba53 100644
>> --- a/security/integrity/ima/ima_main.c
>> +++ b/security/integrity/ima/ima_main.c
>> @@ -921,6 +921,44 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
>>   	fdput(f);
>>   }
>>   
>> +/**
>> + * ima_measure_critical_data - measure kernel subsystem data
>> + * critical to integrity of the kernel
> 
> Please change this to "measure kernel integrity critical data".
> 
*Question*
Thanks Mimi. Do you want us just to update the description, or do you
want us to update the function name too?

I believe you meant just description, but still want to clarify.

ima_measure_kernel_integrity_critical_data() would be too long.
Maybe ima_measure_integrity_critical_data()?

Or do you want us to keep the existing ima_measure_critical_data()?
Could you please let us know?

>> + * @event_data_source: name of the data source being measured;
>> + * typically it should be the name of the kernel subsystem that is sending
>> + * the data for measurement
> 
> Including "data_source" here isn't quite right.  "data source" should
> only be added in the first patch which uses it, not here.   When adding
> it please shorten the field description to "kernel data source".   The
> longer explanation can be included in the longer function description.
> 
*Question*
Do you mean the parameter @event_data_source should be removed from this
patch? And then later added in patch 7/7 – where SeLinux uses it?

But ima_measure_critical_data() calls process_buffer_measurement(), and
p_b_m() accepts it as part of the param @func_data.

What should we pass to p_b_m() @func_data in this patch, if we remove
@event_data_source from this patch?

>> + * @event_name: name of an event from the kernel subsystem that is sending
>> + * the data for measurement
> 
> As this is being passed to process_buffer_measurement(), this should be
> the same or similar to the existing definition.
> 
Ok. I will change this to @eventname to be consistemt with p_b_m().

>> + * @buf: pointer to buffer containing data to measure
>> + * @buf_len: length of buffer(in bytes)
>> + * @measure_buf_hash: if set to true - will measure hash of the buf,
>> + *                    instead of buf
> 
>   kernel doc requires a single line.  In this case, please shorten the
> argument definition to "measure buffer data or buffer data hash".   The
> details can be included in the longer function description.
> 
Sounds good. Will do.
>> + *
>> + * A given kernel subsystem (event_data_source) may send
>> + * data (buf) to be measured when the data or the subsystem state changes.
>> + * The state/data change can be described by event_name.
>> + * Examples of critical data (buf) could be kernel in-memory r/o structures,
>> + * hash of the memory structures, or data that represents subsystem
>> + * state change.
>> + * measure_buf_hash can be used to save space, if the data being measured
>> + * is too large.
>> + * The data (buf) can only be measured, not appraised.
>> + */
> 
> Please remove this longer function description, replacing it something
> more appropriate.  The subsequent patch that introduces the "data
> source" parameter would expand the description.
> 
> thanks,
> 
> Mimi
> 
*Question*
Hi Mimi, will do.
Do you want the data_source to be part of SeLinux patch? (patch 7/7 of
this series).
Or a separate patch before it?
~Tushar

>> +void ima_measure_critical_data(const char *event_data_source,
>> +			       const char *event_name,
>> +			       const void *buf, int buf_len,
>> +			       bool measure_buf_hash)
>> +{
>> +	if (!event_name || !event_data_source || !buf || !buf_len) {
>> +		pr_err("Invalid arguments passed to %s().\n", __func__);
>> +		return;
>> +	}
>> +
>> +	process_buffer_measurement(NULL, buf, buf_len, event_name,
>> +				   CRITICAL_DATA, 0, event_data_source,
>> +				   measure_buf_hash);
>> +}
>> +
>>   static int __init init_ima(void)
>>   {
>>   	int error;

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 4/7] IMA: add policy to measure critical data
  2020-11-06 13:43   ` Mimi Zohar
@ 2020-11-12 22:02     ` Tushar Sugandhi
  0 siblings, 0 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-12 22:02 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel



On 2020-11-06 5:43 a.m., Mimi Zohar wrote:
> Hi Tushar,
> 
> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>> System administrators should be able to choose which kernel subsystems
>> they want to measure the critical data for. To enable that, an IMA policy
>> option to choose specific kernel subsystems is needed. This policy option
>> would constrain the measurement of the critical data to the given kernel
>> subsystems.
> 
> Measuring critical data should not be dependent on the source of the
> critical data.   This patch needs to be split up.  The "data sources"
> should be move to it's own separate patch.  This patch should be
> limited to adding the policy code needed for measuring criticial data.
> Limiting critical data sources should be the last patch in this series.
> 
> thanks,
> 
> Mimi
> 
Thanks Mimi.

Ok. I will split the patches as you suggested.
Patch #1 (this patch) will have the policy code needed for measuring
critical data.
patch #2 Limiting the critical “data_sources”.

*Question 1*
Since you said patch #2 should be the last patch in this series, do you 
mean merging patch #2 with the SeLinux patch? (patch 7/7 of this series)
Or a separate patch before 7/7?

*Question 2*
If I understand it correctly, the following code should be moved from 
this patch to patch #2. Did I miss anything?

  static const match_table_t policy_tokens = {
@@ -957,6 +971,7 @@ static const match_table_t policy_tokens = {
  	{Opt_pcr, "pcr=%s"},
  	{Opt_template, "template=%s"},
  	{Opt_keyrings, "keyrings=%s"},
+	{Opt_data_sources, "data_sources=%s"},
  	{Opt_err, NULL}
  };


+		case Opt_data_sources:
+			ima_log_string(ab, "data_sources",
+				       args[0].from);
+
+			if (entry->data_sources) {
+				result = -EINVAL;
+				break;
+			}
+
+			entry->data_sources = ima_alloc_rule_opt_list(args);
+			if (IS_ERR(entry->data_sources)) {
+				result = PTR_ERR(entry->data_sources);
+				entry->data_sources = NULL;
+				break;
+			}
+
+			entry->flags |= IMA_DATA_SOURCES;
+			break;

+	if (entry->flags & IMA_DATA_SOURCES) {
+		seq_puts(m, "data_sources=");
+		ima_show_rule_opt_list(m, entry->data_sources);
+		seq_puts(m, " ");
+	}
+

~Tushar

>>
>> Add a new IMA policy option - "data_sources:=" to the IMA func
>> CRITICAL_DATA to allow measurement of various kernel subsystems. This
>> policy option would enable the system administrators to limit the
>> measurement to the subsystems listed in "data_sources:=", if the
>> subsystem measures its data by calling ima_measure_critical_data().
>>
>> Limit the measurement to the subsystems that are specified in the IMA
>> policy - CRITICAL_DATA+"data_sources:=". If "data_sources:=" is not
>> provided with the func CRITICAL_DATA, measure the data from all the
>> supported kernel subsystems.
>>
>> Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement
  2020-11-06 14:01   ` Mimi Zohar
@ 2020-11-12 22:09     ` Tushar Sugandhi
  2020-11-13  0:06       ` Mimi Zohar
  0 siblings, 1 reply; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-12 22:09 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel



On 2020-11-06 6:01 a.m., Mimi Zohar wrote:
> Hi Tushar,
> 
> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>> Currently, IMA does not restrict random data sources from measuring
>> their data using ima_measure_critical_data(). Any kernel data source can
>> call the function, and it's data will get measured as long as the input
>> event_data_source is part of the IMA policy - CRITICAL_DATA+data_sources.
>>
>> To ensure that only data from supported sources are measured, the kernel
>> subsystem name needs to be added to a compile-time list of supported
>> sources (an "allowed list of components"). IMA then validates the input
>> parameter - "event_data_source" passed to ima_measure_critical_data()
>> against this allowed list at run-time.
>>
>> This compile-time list must be updated when kernel subsystems are
>> updated to measure their data using IMA.
>>
>> Provide an infrastructure for kernel data sources to be added to
>> IMA's supported data sources list at compile-time. Update
>> ima_measure_critical_data() to validate, at run-time, that the data
>> source is supported before measuring the data coming from that source.
> 
> For those interested in limiting which critical data to measure, the
> "data sources" IMA policy rule option already does that.   Why is this
> needed?
> 
> thanks,
> 
> Mimi
> 

This wasn’t part of the initial series. And I wasn’t convinced if it was
really needed. :) I added it based on the feedback in v2 of this
series. (pasted below for reference[1]).

Maybe I misunderstood your feedback at that time.

*Question*
Could you please let me know if you want us to remove this patch?


[1] From v2 of this series:
https://patchwork.kernel.org/project/linux-integrity/patch/20200821182107.5328-3-tusharsu@linux.microsoft.com/ 


 >>>> "keyrings=" isn't bounded because keyrings can be created by 
userspace.
 >>>> Perhaps keyring names has a minimum/maximum length.  IMA isn't
 >>>> measuring userspace construsts.  Shouldn't the list of critical data
 >>>> being measured be bounded and verified?
 >>> The comment is not entirely clear.
 >>> Do you mean there should be some sort of allow_list in IMA, against
 >>> which the values in "data_sources=" should be vetted? And if the
 >>> value is present in the IMA allow_list, then only the measurements for
 >>> that data source are allowed?
 >>>
 >>> Or do you mean something else?
 >>
 >> Yes, something along those lines.  Does the list of critical data need
 >> to be vetted?  And if so, against what?
 > I am thinking of having an enum and string array - just like ima_hooks
 > and ima_hooks_measure_str in ima.h.
 > And any new kernel component that would support generic IMA measurements
 > in future would have to add itself to the enum/array.
 > And the param *event_data_source in ima_measure_critical_data() will be
 > vetted against the above enum/string array.
 >
 > I will implement it in the next iteration, and hopefully the vetting
 > workflow will be more clear.
 >
 > ~Tushar
 >>
 >> Mimi

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data
  2020-11-05  0:31 ` [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Mimi Zohar
@ 2020-11-12 22:18   ` Tushar Sugandhi
  0 siblings, 0 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-12 22:18 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel



On 2020-11-04 4:31 p.m., Mimi Zohar wrote:
> Hi Tushar,
> 
> Measuring "critical kernel data" is not a new infrastructure, simply a
> new IMA hook.   Please update the above Subject line to "support for
> measuring critical kernel data".
> 
Thanks a lot. Will update.
> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>> There are several kernel subsystems that contain critical data which if
>> accidentally or maliciously altered, can compromise the integrity of the
>> system. Examples of such subsystems would include LSMs like SELinux, or
>> AppArmor; or device-mapper targets like dm-crypt, dm-verity etc.
>> "critical data" in this context is kernel subsystem specific information
>> that is stored in kernel memory. Examples of critical data could be
>> kernel in-memory r/o structures, hash of the memory structures, or
>> data that represents a linux kernel subsystem state.
> 
> This is a bit better, but needs to be much clearer.  Please define
> "critical data", not by example, but by describing "what" critical
> kernel data is.  "There are several kernel subsystems ...."  is an
> example of "how" it would be used, not a definition.  Without a clear
> definition it will become a dumping ground for measuring anything
> anyone wants to measure.  As a result, it may be abused.
> 
Good point. I will come up with a better definition.
>>
>> This patch set defines a new IMA hook namely CRITICAL_DATA, and a
>> function ima_measure_critical_data() - to measure the critical data.
> 
> The name of the IMA hook is ima_measure_critical_data.  This is similar
> to the LSM hooks, which are prefixed with "security_".  (For a full
> list of LSM hooks, refer to lsm_hook_defs.h.)
> 
Thanks for the clarification. I will update this description.
>> Kernel subsystems can use this functionality, to take advantage of IMA's
>> measuring and quoting abilities - thus ultimately enabling remote
>> attestation for the subsystem specific information stored in the kernel
>> memory.
>>
>> The functionality is generic enough to measure the data of any kernel
>> subsystem at run-time. To ensure that only data from supported sources
>> are measured, the kernel subsystem needs to be added to a compile-time
>> list of supported sources (an "allowed list of components"). IMA
>> validates the source passed to ima_measure_critical_data() against this
>> allowed list at run-time.
> 
> Yes, this new feature is generic, but one of the main goals of IMA is
> to measure and attest to the integrity of the system, not to measure
> and attest to random things.
> 
Ok. I will update the above paragraph accordingly.
>>
>> System administrators may want to pick and choose which kernel
>> subsystem information they would want to enable for measurements,
>> quoting, and remote attestation. To enable that, a new IMA policy is
>> introduced.
> 
> ^may want to limit the critical data being measured, quoted and
> attested.
> ^ a new IMA policy condition is defined.
> 
Sounds good. Will update.
>>
>> This patch set also addresses the need for the kernel subsystems to
>> measure their data before a custom IMA policy is loaded - by providing
>> a builtin IMA policy.
> 
> ^for measuring kernel critical data early, before a custom IMA policy
> ...
> 
Sounds good. Will update.
>>
>> And lastly, the use of the overall functionality is demonstrated by
>> measuring the kernel in-memory data for one such subsystem - SeLinux.
> 
> The purpose isn't to demonstrate the "overall functionality", but to
> provide an initial caller of the new IMA hook.
> 
Fair point. Will change the description accordingly.
~Tushar

> thanks,
> 
> Mimi
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash
  2020-11-12 21:47     ` Tushar Sugandhi
@ 2020-11-12 22:19       ` Mimi Zohar
  2020-11-12 23:16         ` Tushar Sugandhi
  0 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-12 22:19 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

On Thu, 2020-11-12 at 13:47 -0800, Tushar Sugandhi wrote:
> > On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
> >> process_buffer_measurement() currently only measures the input buffer.
> >> In case of SeLinux policy measurement, the policy being measured could
> >> be large (several MB). This may result in a large entry in IMA
> >> measurement log.
> > 
> > SELinux is an example of measuring large buffer data.  Please rewrite
> > this patch description (and the other patch descriptions in this patch
> > set) without using the example to describe its purpose [1].
> > 
> > In this case, you might say,
> > 
> > The original IMA buffer data measurement sizes were small (e.g. boot
> > command line), but new buffer data measurement use cases are a lot
> > larger.  Just as IMA measures the file data hash, not the file data,
> > IMA should similarly support measuring the buffer data hash.
> > 
> Sure. Thanks a lot for giving an example wording for us. Will update.
> >>
> >> Introduce a boolean parameter measure_buf_hash to support measuring
> >> hash of a buffer, which would be much smaller, instead of the buffer
> >> itself.
> > 
> >> To use the functionality introduced in this patch, the attestation
> >> client and the server changes need to go hand in hand. The
> >> client/kernel would know what data is being measured as-is
> >> (e.g. KEXEC_CMDLINE), and what data has it’s hash measured (e.g. SeLinux
> >> Policy). And the attestation server should verify data/hash accordingly.
> >>
> >> Just like the data being measured in other cases, the attestation server
> >> will know what are possible values of the large buffers being measured.
> >> e.g. the possible valid SeLinux policy values that are being pushed to
> >> the client. The attestation server will have to maintain the hash of
> >> those buffer values.
> > 
> > Each patch in the patch set builds upon the previous one.   (Think of
> > it as a story, where each chapter builds upon the previous ones.)
> > With rare exceptions, should patches reference subsequent patches. [2]
> > 
> > [1] Refer to Documentation/process/submitting-patches.rst
> > [2] Refer to the section "8) Commenting" in
> > Documentation/process/coding-style.rst
> > 
> I am not sure if you have any concerns about the last two paragraphs.
> The description about the attestation client and server (the last two
> paragraphs) was added for information/clarification purpose only, as per
> your feedback on previous iterations. The subsequent patches don’t have
> any code pertaining to attestation client/server.
> 
> *Question*
> Maybe the last two paragraphs are confusing/redundant. Could you please
> let me know if I should remove the above two paragraphs altogether? 
> (starting with “To use the functionality introduced in this patch ...”)
> 
> If we decide to keep the paragraphs, I will remove the specific examples
> (KEXEC_CMDLINE, SeLinux etc.) as you mentioned elsewhere.

Instead of the above two paragraphs, perhaps explain how measuring the
file data hash differs from measuring the buffer data hash.  Keep the
explanation generic, short and simple.

Mimi


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash
  2020-11-12 22:19       ` Mimi Zohar
@ 2020-11-12 23:16         ` Tushar Sugandhi
  0 siblings, 0 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-12 23:16 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel



On 2020-11-12 2:19 p.m., Mimi Zohar wrote:
> On Thu, 2020-11-12 at 13:47 -0800, Tushar Sugandhi wrote:
>>> On Sun, 2020-11-01 at 14:26 -0800, Tushar Sugandhi wrote:
>>>> process_buffer_measurement() currently only measures the input buffer.
>>>> In case of SeLinux policy measurement, the policy being measured could
>>>> be large (several MB). This may result in a large entry in IMA
>>>> measurement log.
>>>
>>> SELinux is an example of measuring large buffer data.  Please rewrite
>>> this patch description (and the other patch descriptions in this patch
>>> set) without using the example to describe its purpose [1].
>>>
>>> In this case, you might say,
>>>
>>> The original IMA buffer data measurement sizes were small (e.g. boot
>>> command line), but new buffer data measurement use cases are a lot
>>> larger.  Just as IMA measures the file data hash, not the file data,
>>> IMA should similarly support measuring the buffer data hash.
>>>
>> Sure. Thanks a lot for giving an example wording for us. Will update.
>>>>
>>>> Introduce a boolean parameter measure_buf_hash to support measuring
>>>> hash of a buffer, which would be much smaller, instead of the buffer
>>>> itself.
>>>
>>>> To use the functionality introduced in this patch, the attestation
>>>> client and the server changes need to go hand in hand. The
>>>> client/kernel would know what data is being measured as-is
>>>> (e.g. KEXEC_CMDLINE), and what data has it’s hash measured (e.g. SeLinux
>>>> Policy). And the attestation server should verify data/hash accordingly.
>>>>
>>>> Just like the data being measured in other cases, the attestation server
>>>> will know what are possible values of the large buffers being measured.
>>>> e.g. the possible valid SeLinux policy values that are being pushed to
>>>> the client. The attestation server will have to maintain the hash of
>>>> those buffer values.
>>>
>>> Each patch in the patch set builds upon the previous one.   (Think of
>>> it as a story, where each chapter builds upon the previous ones.)
>>> With rare exceptions, should patches reference subsequent patches. [2]
>>>
>>> [1] Refer to Documentation/process/submitting-patches.rst
>>> [2] Refer to the section "8) Commenting" in
>>> Documentation/process/coding-style.rst
>>>
>> I am not sure if you have any concerns about the last two paragraphs.
>> The description about the attestation client and server (the last two
>> paragraphs) was added for information/clarification purpose only, as per
>> your feedback on previous iterations. The subsequent patches don’t have
>> any code pertaining to attestation client/server.
>>
>> *Question*
>> Maybe the last two paragraphs are confusing/redundant. Could you please
>> let me know if I should remove the above two paragraphs altogether?
>> (starting with “To use the functionality introduced in this patch ...”)
>>
>> If we decide to keep the paragraphs, I will remove the specific examples
>> (KEXEC_CMDLINE, SeLinux etc.) as you mentioned elsewhere.
> 
> Instead of the above two paragraphs, perhaps explain how measuring the
> file data hash differs from measuring the buffer data hash.  Keep the
> explanation generic, short and simple.
> 
> Mimi
> 
Will do. Thanks for the quick response Mimi.
I also have some clarification questions on the other patches in this
series as well.

Would really appreciate if you could help us get clarification on those.

Thanks a lot again.

~Tushar

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 3/7] IMA: add hook to measure critical data
  2020-11-12 21:57     ` Tushar Sugandhi
@ 2020-11-12 23:56       ` Mimi Zohar
  2020-11-13 17:23         ` Tushar Sugandhi
  0 siblings, 1 reply; 31+ messages in thread
From: Mimi Zohar @ 2020-11-12 23:56 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

On Thu, 2020-11-12 at 13:57 -0800, Tushar Sugandhi wrote:
> >> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> >> index 4485d87c0aa5..6e1b11dcba53 100644
> >> --- a/security/integrity/ima/ima_main.c
> >> +++ b/security/integrity/ima/ima_main.c
> >> @@ -921,6 +921,44 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
> >>   	fdput(f);
> >>   }
> >>   
> >> +/**
> >> + * ima_measure_critical_data - measure kernel subsystem data
> >> + * critical to integrity of the kernel
> > 
> > Please change this to "measure kernel integrity critical data".
> > 
> *Question*
> Thanks Mimi. Do you want us just to update the description, or do you
> want us to update the function name too?

Just the description.

> 
> I believe you meant just description, but still want to clarify.
> 
> ima_measure_kernel_integrity_critical_data() would be too long.
> Maybe ima_measure_integrity_critical_data()?
> 
> Or do you want us to keep the existing ima_measure_critical_data()?
> Could you please let us know?
> 
> >> + * @event_data_source: name of the data source being measured;
> >> + * typically it should be the name of the kernel subsystem that is sending
> >> + * the data for measurement
> > 
> > Including "data_source" here isn't quite right.  "data source" should
> > only be added in the first patch which uses it, not here.   When adding
> > it please shorten the field description to "kernel data source".   The
> > longer explanation can be included in the longer function description.
> > 
> *Question*
> Do you mean the parameter @event_data_source should be removed from this
> patch? And then later added in patch 7/7 – where SeLinux uses it?

Data source support doesn't belong in this patch.  Each patch should do
one logical thing and only that one thing.  This patch is adding
support for measuring critical data.  The data source patch will limit
the critical data being measured.

Other than updating the data source list in the documentation,
definitely do not add data source support to the SELinux patch.

thanks,

Mimi


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement
  2020-11-12 22:09     ` Tushar Sugandhi
@ 2020-11-13  0:06       ` Mimi Zohar
  0 siblings, 0 replies; 31+ messages in thread
From: Mimi Zohar @ 2020-11-13  0:06 UTC (permalink / raw)
  To: Tushar Sugandhi, stephen.smalley.work, casey, agk, snitzer,
	gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel

Hi Tushar,

On Thu, 2020-11-12 at 14:09 -0800, Tushar Sugandhi wrote:
> Could you please let me know if you want us to remove this patch?

As neither of us are convinced this is necessary, please drop it.

Mimi


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH v5 3/7] IMA: add hook to measure critical data
  2020-11-12 23:56       ` Mimi Zohar
@ 2020-11-13 17:23         ` Tushar Sugandhi
  0 siblings, 0 replies; 31+ messages in thread
From: Tushar Sugandhi @ 2020-11-13 17:23 UTC (permalink / raw)
  To: Mimi Zohar, stephen.smalley.work, casey, agk, snitzer, gmazyland, paul
  Cc: tyhicks, sashal, jmorris, nramas, linux-integrity, selinux,
	linux-security-module, linux-kernel, dm-devel


>>> Including "data_source" here isn't quite right.  "data source" should
>>> only be added in the first patch which uses it, not here.   When adding
>>> it please shorten the field description to "kernel data source".   The
>>> longer explanation can be included in the longer function description.
>>>
>> *Question*
>> Do you mean the parameter @event_data_source should be removed from this
>> patch? And then later added in patch 7/7 – where SeLinux uses it?
> 
> Data source support doesn't belong in this patch.  Each patch should do
> one logical thing and only that one thing.  This patch is adding
> support for measuring critical data.  The data source patch will limit
> the critical data being measured.
> 
> Other than updating the data source list in the documentation,
> definitely do not add data source support to the SELinux patch.
> 
> thanks,
> 
> Mimi
> 
Makes sense, I will move the data_source from this patch to a
separate one before SeLinux.
And the SeLinux patch will simply update the documentation.

Thanks Mimi.

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2020-11-13 17:23 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-01 22:26 [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Tushar Sugandhi
2020-11-01 22:26 ` [PATCH v5 1/7] IMA: generalize keyring specific measurement constructs Tushar Sugandhi
2020-11-01 22:26 ` [PATCH v5 2/7] IMA: update process_buffer_measurement to measure buffer hash Tushar Sugandhi
2020-11-05 14:30   ` Mimi Zohar
2020-11-12 21:47     ` Tushar Sugandhi
2020-11-12 22:19       ` Mimi Zohar
2020-11-12 23:16         ` Tushar Sugandhi
2020-11-06 12:11   ` Mimi Zohar
2020-11-12 21:48     ` Tushar Sugandhi
2020-11-01 22:26 ` [PATCH v5 3/7] IMA: add hook to measure critical data Tushar Sugandhi
2020-11-06 13:24   ` Mimi Zohar
2020-11-12 21:57     ` Tushar Sugandhi
2020-11-12 23:56       ` Mimi Zohar
2020-11-13 17:23         ` Tushar Sugandhi
2020-11-01 22:26 ` [PATCH v5 4/7] IMA: add policy " Tushar Sugandhi
2020-11-06 13:43   ` Mimi Zohar
2020-11-12 22:02     ` Tushar Sugandhi
2020-11-01 22:26 ` [PATCH v5 5/7] IMA: validate supported kernel data sources before measurement Tushar Sugandhi
2020-11-06 14:01   ` Mimi Zohar
2020-11-12 22:09     ` Tushar Sugandhi
2020-11-13  0:06       ` Mimi Zohar
2020-11-01 22:26 ` [PATCH v5 6/7] IMA: add critical_data to the built-in policy rules Tushar Sugandhi
2020-11-06 15:24   ` Mimi Zohar
2020-11-06 15:37     ` Lakshmi Ramasubramanian
2020-11-06 23:51       ` Lakshmi Ramasubramanian
2020-11-08 15:46         ` Mimi Zohar
2020-11-09 17:24           ` Lakshmi Ramasubramanian
2020-11-01 22:26 ` [PATCH v5 7/7] selinux: measure state and hash of the policy using IMA Tushar Sugandhi
2020-11-06 15:47   ` Mimi Zohar
2020-11-05  0:31 ` [PATCH v5 0/7] IMA: Infrastructure for measurement of critical kernel data Mimi Zohar
2020-11-12 22:18   ` Tushar Sugandhi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).