linux-security-module.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/4] LSM: Measure security module data
@ 2020-07-30  3:47 Lakshmi Ramasubramanian
  2020-07-30  3:47 ` [PATCH v5 1/4] IMA: Add func to measure LSM state and policy Lakshmi Ramasubramanian
                   ` (3 more replies)
  0 siblings, 4 replies; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30  3:47 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

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 configuration that the system administrator had setup. The policies
and configuration for the security modules could be tampered with by
malware by exploiting kernel vulnerabilities or modified through some
inadvertent actions on the system. Measuring such critical data would
enable an attestation service to better assess the state of the system.

IMA subsystem measures system files, command line arguments passed to
kexec, boot aggregate, keys, etc. It can be used to measure critical
data structures of security modules as well.

This change aims to address measuring critical data structures
of security modules when they are initialized and when they are
updated at runtime.

This series is based on commit 3db0d0c276a7 ("integrity: remove
redundant initialization of variable ret") in next-integrity

Change log:

  v5:
      => Append timestamp to "event name" string in the call to
         the IMA hooks so that LSM data is always measured by IMA.
      => Removed workqueue patch that was handling periodic checking
         of the LSM data. This change will be introduced as a separate
         patch set while keeping this patch set focussed on measuring
         the LSM data on initialization and on updates at runtime.
      => Handle early boot measurement of LSM data.

  v4:
      => Added LSM_POLICY func and IMA hook to measure LSM policy.
      => Pass SELinux policy data, instead of the hash of the policy,
         to the IMA hook to measure.
      => Include "initialized" flag in SELinux measurement.
         Also, measure SELinux state even when initialization is not yet
         completed. But measure SELinux policy only after initialization.

  v3:
      => Loop through policy_capabilities to build the state data
         to measure instead of hardcoding to current set of
         policy capabilities.
      => Added error log messages for failure conditions.

  v2:
      => Pass selinux_state struct as parameter to the function
         that measures SELinux data.
      => Use strings from selinux_policycap_names array for SELinux
         state measurement.
      => Refactored security_read_policy() to alloc kernel or user
         virtual memory and then read the SELinux policy.

  v1:
      => Per Stephen Smalley's suggestion added selinux_state booleans
         and hash of SELinux policy in the measured data for SELinux.
      => Call IMA hook from the security module directly instead of
         redirecting through the LSM.

Lakshmi Ramasubramanian (4):
  IMA: Add func to measure LSM state and policy
  IMA: Define IMA hooks to measure LSM state and policy
  LSM: Define SELinux function to measure state and policy
  IMA: Handle early boot data measurement

 Documentation/ABI/testing/ima_policy         |   9 +
 include/linux/ima.h                          |  14 ++
 security/integrity/ima/Kconfig               |   5 +-
 security/integrity/ima/Makefile              |   2 +-
 security/integrity/ima/ima.h                 |  45 +++--
 security/integrity/ima/ima_api.c             |   2 +-
 security/integrity/ima/ima_asymmetric_keys.c |   6 +-
 security/integrity/ima/ima_init.c            |   2 +-
 security/integrity/ima/ima_main.c            |  64 ++++++-
 security/integrity/ima/ima_policy.c          |  33 +++-
 security/integrity/ima/ima_queue_data.c      | 175 +++++++++++++++++++
 security/integrity/ima/ima_queue_keys.c      | 174 ------------------
 security/selinux/Makefile                    |   2 +
 security/selinux/hooks.c                     |   1 +
 security/selinux/include/security.h          |  15 ++
 security/selinux/measure.c                   | 150 ++++++++++++++++
 security/selinux/selinuxfs.c                 |   3 +
 security/selinux/ss/services.c               |  71 +++++++-
 18 files changed, 551 insertions(+), 222 deletions(-)
 create mode 100644 security/integrity/ima/ima_queue_data.c
 delete mode 100644 security/integrity/ima/ima_queue_keys.c
 create mode 100644 security/selinux/measure.c

-- 
2.27.0


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

* [PATCH v5 1/4] IMA: Add func to measure LSM state and policy
  2020-07-30  3:47 [PATCH v5 0/4] LSM: Measure security module data Lakshmi Ramasubramanian
@ 2020-07-30  3:47 ` Lakshmi Ramasubramanian
  2020-07-30 15:02   ` Tyler Hicks
  2020-07-30  3:47 ` [PATCH v5 2/4] IMA: Define IMA hooks " Lakshmi Ramasubramanian
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30  3:47 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

Critical data structures of security modules need to be measured to
enable an attestation service to verify if the configuration and
policies for the security modules have been setup correctly and
that they haven't been tampered with at runtime. A new IMA policy is
required for handling this measurement.

Define two new IMA policy func namely LSM_STATE and LSM_POLICY to
measure the state and the policy provided by the security modules.
Update ima_match_rules() and ima_validate_rule() to check for
the new func and ima_parse_rule() to handle the new func.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 Documentation/ABI/testing/ima_policy |  9 ++++++++
 security/integrity/ima/ima.h         |  2 ++
 security/integrity/ima/ima_api.c     |  2 +-
 security/integrity/ima/ima_policy.c  | 31 ++++++++++++++++++++++++----
 4 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index cd572912c593..b7c7fb548c0c 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -30,6 +30,7 @@ Description:
 				[FIRMWARE_CHECK]
 				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
 				[KEXEC_CMDLINE] [KEY_CHECK]
+				[LSM_STATE] [LSM_POLICY]
 			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
 			       [[^]MAY_EXEC]
 			fsmagic:= hex value
@@ -125,3 +126,11 @@ Description:
 		keys added to .builtin_trusted_keys or .ima keyring:
 
 			measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima
+
+		Example of measure rule using LSM_STATE to measure LSM state:
+
+			measure func=LSM_STATE template=ima-buf
+
+		Example of measure rule using LSM_POLICY to measure LSM policy:
+
+			measure func=LSM_POLICY template=ima-ng
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 38043074ce5e..1b5f4b2f17d0 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -200,6 +200,8 @@ static inline unsigned int ima_hash_key(u8 *digest)
 	hook(POLICY_CHECK, policy)			\
 	hook(KEXEC_CMDLINE, kexec_cmdline)		\
 	hook(KEY_CHECK, key)				\
+	hook(LSM_STATE, lsm_state)			\
+	hook(LSM_POLICY, lsm_policy)			\
 	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 4f39fb93f278..8c8b4e4a6493 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 | LSM_STATE | LSM_POLICY
  *	mask: contains the permission mask
  *	fsmagic: hex value
  *
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 07f033634b27..a0f5c39d9084 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -442,13 +442,20 @@ 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_keyring(rule, keyring, cred);
-	}
 	if ((rule->flags & IMA_FUNC) &&
 	    (rule->func != func && func != POST_SETATTR))
 		return false;
+
+	switch (func) {
+	case KEY_CHECK:
+		return ima_match_keyring(rule, keyring, cred);
+	case LSM_STATE:
+	case LSM_POLICY:
+		return true;
+	default:
+		break;
+	}
+
 	if ((rule->flags & IMA_MASK) &&
 	    (rule->mask != mask && func != POST_SETATTR))
 		return false;
@@ -1044,6 +1051,18 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
 		if (ima_rule_contains_lsm_cond(entry))
 			return false;
 
+		break;
+	case LSM_STATE:
+	case LSM_POLICY:
+		if (entry->action & ~(MEASURE | DONT_MEASURE))
+			return false;
+
+		if (entry->flags & ~(IMA_FUNC | IMA_PCR))
+			return false;
+
+		if (ima_rule_contains_lsm_cond(entry))
+			return false;
+
 		break;
 	default:
 		return false;
@@ -1176,6 +1195,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
 				entry->func = KEXEC_CMDLINE;
 			else if (strcmp(args[0].from, "KEY_CHECK") == 0)
 				entry->func = KEY_CHECK;
+			else if (strcmp(args[0].from, "LSM_STATE") == 0)
+				entry->func = LSM_STATE;
+			else if (strcmp(args[0].from, "LSM_POLICY") == 0)
+				entry->func = LSM_POLICY;
 			else
 				result = -EINVAL;
 			if (!result)
-- 
2.27.0


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

* [PATCH v5 2/4] IMA: Define IMA hooks to measure LSM state and policy
  2020-07-30  3:47 [PATCH v5 0/4] LSM: Measure security module data Lakshmi Ramasubramanian
  2020-07-30  3:47 ` [PATCH v5 1/4] IMA: Add func to measure LSM state and policy Lakshmi Ramasubramanian
@ 2020-07-30  3:47 ` Lakshmi Ramasubramanian
  2020-07-30 15:04   ` Tyler Hicks
  2020-07-30  3:47 ` [PATCH v5 3/4] LSM: Define SELinux function to measure " Lakshmi Ramasubramanian
  2020-07-30  3:47 ` [PATCH v5 4/4] IMA: Handle early boot data measurement Lakshmi Ramasubramanian
  3 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30  3:47 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

IMA subsystem needs to define IMA hooks that the security modules can
call to measure state and policy data.

Define two new IMA hooks, namely ima_lsm_state() and ima_lsm_policy(),
that the security modules can call to measure LSM state and LSM policy
respectively. Return the status of the measurement operation from these
two IMA hooks.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 include/linux/ima.h               | 14 +++++++++
 security/integrity/ima/ima.h      |  6 ++--
 security/integrity/ima/ima_main.c | 50 ++++++++++++++++++++++++++-----
 3 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index d15100de6cdd..442ca0dce3c8 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -26,6 +26,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 int ima_measure_lsm_state(const char *lsm_event_name, const void *buf,
+				 int size);
+extern int ima_measure_lsm_policy(const char *lsm_event_name, const void *buf,
+				  int size);
 
 #ifdef CONFIG_IMA_KEXEC
 extern void ima_add_kexec_buffer(struct kimage *image);
@@ -104,6 +108,16 @@ 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 int ima_measure_lsm_state(const char *lsm_event_name,
+					const void *buf, int size)
+{
+	return -EOPNOTSUPP;
+}
+static inline int ima_measure_lsm_policy(const char *lsm_event_name,
+					 const void *buf, int size)
+{
+	return -EOPNOTSUPP;
+}
 #endif /* CONFIG_IMA */
 
 #ifndef CONFIG_IMA_KEXEC
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 1b5f4b2f17d0..8ed9f5e1dd40 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -267,9 +267,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
 			   struct evm_ima_xattr_data *xattr_value,
 			   int xattr_len, const struct modsig *modsig, int pcr,
 			   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 process_buffer_measurement(struct inode *inode, const void *buf, int size,
+			       const char *eventname, enum ima_hooks func,
+			       int pcr, const char *keyring);
 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_main.c b/security/integrity/ima/ima_main.c
index 8a91711ca79b..74d421e40c8f 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -736,9 +736,9 @@ int ima_load_data(enum kernel_load_data_id id)
  *
  * 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 process_buffer_measurement(struct inode *inode, const void *buf, int size,
+			       const char *eventname, enum ima_hooks func,
+			       int pcr, const char *keyring)
 {
 	int ret = 0;
 	const char *audit_cause = "ENOMEM";
@@ -758,7 +758,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 	u32 secid;
 
 	if (!ima_policy_flag)
-		return;
+		return 0;
 
 	/*
 	 * Both LSM hooks and auxilary based buffer measurements are
@@ -772,7 +772,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 		action = ima_get_action(inode, current_cred(), secid, 0, func,
 					&pcr, &template, keyring);
 		if (!(action & IMA_MEASURE))
-			return;
+			return 0;
 	}
 
 	if (!pcr)
@@ -787,7 +787,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 			pr_err("template %s init failed, result: %d\n",
 			       (strlen(template->name) ?
 				template->name : template->fmt), ret);
-			return;
+			return ret;
 		}
 	}
 
@@ -819,7 +819,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
 					func_measure_str(func),
 					audit_cause, ret, 0, ret);
 
-	return;
+	return ret;
 }
 
 /**
@@ -846,6 +846,42 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
 	fdput(f);
 }
 
+/**
+ * ima_measure_lsm_state - measure LSM specific state
+ * @lsm_event_name: LSM event
+ * @buf: pointer to buffer containing LSM specific state
+ * @size: Number of bytes in buf
+ *
+ * Buffers can only be measured, not appraised.
+ */
+int ima_measure_lsm_state(const char *lsm_event_name, const void *buf,
+			  int size)
+{
+	if (!lsm_event_name || !buf || !size)
+		return -EINVAL;
+
+	return process_buffer_measurement(NULL, buf, size, lsm_event_name,
+					  LSM_STATE, 0, NULL);
+}
+
+/**
+ * ima_measure_lsm_policy - measure LSM specific policy
+ * @lsm_event_name: LSM event
+ * @buf: pointer to buffer containing LSM specific policy
+ * @size: Number of bytes in buf
+ *
+ * Buffers can only be measured, not appraised.
+ */
+int ima_measure_lsm_policy(const char *lsm_event_name, const void *buf,
+			   int size)
+{
+	if (!lsm_event_name || !buf || !size)
+		return -EINVAL;
+
+	return process_buffer_measurement(NULL, buf, size, lsm_event_name,
+					  LSM_POLICY, 0, NULL);
+}
+
 static int __init init_ima(void)
 {
 	int error;
-- 
2.27.0


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

* [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-07-30  3:47 [PATCH v5 0/4] LSM: Measure security module data Lakshmi Ramasubramanian
  2020-07-30  3:47 ` [PATCH v5 1/4] IMA: Add func to measure LSM state and policy Lakshmi Ramasubramanian
  2020-07-30  3:47 ` [PATCH v5 2/4] IMA: Define IMA hooks " Lakshmi Ramasubramanian
@ 2020-07-30  3:47 ` Lakshmi Ramasubramanian
  2020-08-03 15:11   ` Stephen Smalley
  2020-07-30  3:47 ` [PATCH v5 4/4] IMA: Handle early boot data measurement Lakshmi Ramasubramanian
  3 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30  3:47 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

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

Measure SELinux configuration, policy capabilities settings, and the
loaded policy by calling the IMA hooks ima_measure_lsm_state() and
ima_measure_lsm_policy() respectively.

Sample measurement of SELinux state and hash of the policy:

10 e32e...5ac3 ima-buf sha256:86e8...4594 selinux-state-1595389364:287899386 696e697469616c697a65643d313b656e61626c65643d313b656e666f7263696e673d303b636865636b72657170726f743d313b6e6574776f726b5f706565725f636f6e74726f6c733d313b6f70656e5f7065726d733d313b657874656e6465645f736f636b65745f636c6173733d313b616c776179735f636865636b5f6e6574776f726b3d303b6367726f75705f7365636c6162656c3d313b6e6e705f6e6f737569645f7472616e736974696f6e3d313b67656e66735f7365636c6162656c5f73796d6c696e6b733d303
10 f4a7...9408 ima-ng sha256:8d1d...1834 selinux-policy-hash-1595389353:863934271

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 -m 1 "selinux-state" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | 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

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 -m 1 "selinux-policy-hash" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | cut -d' ' -f 4

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Reported-by: kernel test robot <lkp@intel.com> # error: implicit declaration of function 'vfree'
Reported-by: kernel test robot <lkp@intel.com> # error: implicit declaration of function 'crypto_alloc_shash'
Reported-by: kernel test robot <lkp@intel.com> # sparse: symbol 'security_read_selinux_policy' was not declared. Should it be static?
---
 security/selinux/Makefile           |   2 +
 security/selinux/hooks.c            |   1 +
 security/selinux/include/security.h |  15 +++
 security/selinux/measure.c          | 150 ++++++++++++++++++++++++++++
 security/selinux/selinuxfs.c        |   3 +
 security/selinux/ss/services.c      |  71 +++++++++++--
 6 files changed, 233 insertions(+), 9 deletions(-)
 create mode 100644 security/selinux/measure.c

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 efa6108b1ce9..5521dfc1900b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7394,6 +7394,7 @@ int selinux_disable(struct selinux_state *state)
 	}
 
 	selinux_mark_disabled(state);
+	selinux_measure_state(state);
 
 	pr_info("SELinux:  Disabled at runtime.\n");
 
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index b0e02cfe3ce1..77f42d9b544b 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -222,16 +222,31 @@ static inline bool selinux_policycap_genfs_seclabel_symlinks(void)
 	return state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS];
 }
 
+static inline bool selinux_checkreqprot(const struct selinux_state *state)
+{
+	return READ_ONCE(state->checkreqprot);
+}
+
 int security_mls_enabled(struct selinux_state *state);
 int security_load_policy(struct selinux_state *state,
 			 void *data, size_t len);
 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);
 size_t security_policydb_len(struct selinux_state *state);
 
 int security_policycap_supported(struct selinux_state *state,
 				 unsigned int req_cap);
 
+#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
+
 #define SEL_VEC_MAX 32
 struct av_decision {
 	u32 allowed;
diff --git a/security/selinux/measure.c b/security/selinux/measure.c
new file mode 100644
index 000000000000..1583628d09d1
--- /dev/null
+++ b/security/selinux/measure.c
@@ -0,0 +1,150 @@
+// 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 an 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 an 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 curr_time;
+	int count;
+
+	ktime_get_real_ts64(&curr_time);
+	count = snprintf(NULL, 0, "%s-%lld:%09ld", name_prefix,
+			 curr_time.tv_sec, curr_time.tv_nsec);
+	count++;
+	event_name = kzalloc(count, GFP_KERNEL);
+	if (!event_name) {
+		pr_warn("%s: event name not allocated.\n", __func__);
+		return NULL;
+	}
+
+	snprintf(event_name, count, "%s-%lld:%09ld", name_prefix,
+		 curr_time.tv_sec, curr_time.tv_nsec);
+
+	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;
+
+	buf_len = snprintf(NULL, 0, str_fmt, "initialized", 0);
+	buf_len += snprintf(NULL, 0, str_fmt, "enabled", 0);
+	buf_len += snprintf(NULL, 0, str_fmt, "enforcing", 0);
+	buf_len += snprintf(NULL, 0, str_fmt, "checkreqprot", 0);
+
+	for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) {
+		buf_len += snprintf(NULL, 0, str_fmt,
+				    selinux_policycap_names[i], 0);
+	}
+	++buf_len;
+
+	buf = kzalloc(buf_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	curr = snprintf(buf, buf_len, str_fmt,
+			"initialized", selinux_initialized(state));
+	curr += snprintf((buf + curr), (buf_len - curr), str_fmt,
+			 "enabled", !selinux_disabled(state));
+	curr += snprintf((buf + curr), (buf_len - curr), str_fmt,
+			 "enforcing", enforcing_enabled(state));
+	curr += snprintf((buf + curr), (buf_len - curr), str_fmt,
+			 "checkreqprot", selinux_checkreqprot(state));
+
+	for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) {
+		curr += snprintf((buf + curr), (buf_len - curr), str_fmt,
+				 selinux_policycap_names[i],
+				 state->policycap[i]);
+	}
+
+	*state_str = buf;
+	*state_str_len = curr;
+
+	return 0;
+}
+
+void selinux_measure_state(struct selinux_state *state)
+{
+	void *policy = NULL;
+	char *event_name = NULL;
+	char *state_str = NULL;
+	size_t policy_len;
+	int state_str_len, rc = 0;
+	bool initialized = selinux_initialized(state);
+
+	rc = read_selinux_state(&state_str, &state_str_len, state);
+	if (rc) {
+		pr_warn("%s: Failed to read selinux state.\n", __func__);
+		return;
+	}
+
+	/*
+	 * Get an unique string for measuring the current SELinux state.
+	 */
+	event_name = selinux_event_name("selinux-state");
+	if (!event_name) {
+		pr_warn("%s: Event name for state not allocated.\n",
+			__func__);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = ima_measure_lsm_state(event_name, state_str, state_str_len);
+
+	kfree(event_name);
+	event_name = NULL;
+
+	if (rc)
+		goto out;
+
+	/*
+	 * Measure SELinux policy only after initialization is completed.
+	 */
+	if (!initialized)
+		goto out;
+
+	rc = security_read_policy_kernel(state, &policy, &policy_len);
+	if (rc)
+		goto out;
+
+	event_name = selinux_event_name("selinux-policy-hash");
+	if (!event_name) {
+		pr_warn("%s: Event name for policy not allocated.\n",
+			__func__);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = ima_measure_lsm_policy(event_name, policy, policy_len);
+
+out:
+	kfree(event_name);
+	kfree(state_str);
+	vfree(policy);
+}
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 4781314c2510..6d46eaef5c92 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -173,6 +173,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
 			from_kuid(&init_user_ns, audit_get_loginuid(current)),
 			audit_get_sessionid(current));
 		enforcing_set(state, new_value);
+		selinux_measure_state(state);
 		if (new_value)
 			avc_ss_reset(state->avc, 0);
 		selnl_notify_setenforce(new_value);
@@ -678,6 +679,8 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
 
 	fsi->state->checkreqprot = new_value ? 1 : 0;
 	length = count;
+
+	selinux_measure_state(fsi->state);
 out:
 	kfree(page);
 	return length;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index ef0afd878bfc..3978c804c361 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2182,6 +2182,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
 		selinux_status_update_policyload(state, seqno);
 		selinux_netlbl_cache_invalidate();
 		selinux_xfrm_notify_policyload();
+		selinux_measure_state(state);
 		return 0;
 	}
 
@@ -2270,6 +2271,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
 	selinux_status_update_policyload(state, seqno);
 	selinux_netlbl_cache_invalidate();
 	selinux_xfrm_notify_policyload();
+	selinux_measure_state(state);
 
 	rc = 0;
 	goto out;
@@ -2941,6 +2943,7 @@ int security_set_bools(struct selinux_state *state, u32 len, int *values)
 		selnl_notify_policyload(seqno);
 		selinux_status_update_policyload(state, seqno);
 		selinux_xfrm_notify_policyload();
+		selinux_measure_state(state);
 	}
 	return rc;
 }
@@ -3720,14 +3723,23 @@ int security_netlbl_sid_to_secattr(struct selinux_state *state,
 }
 #endif /* CONFIG_NETLABEL */
 
+static int security_read_policy_len(struct selinux_state *state, size_t *len)
+{
+	if (!selinux_initialized(state))
+		return -EINVAL;
+
+	*len = security_policydb_len(state);
+	return 0;
+}
+
 /**
- * security_read_policy - read the policy.
+ * security_read_selinux_policy - read the policy.
  * @data: binary policy data
  * @len: length of data in bytes
  *
  */
-int security_read_policy(struct selinux_state *state,
-			 void **data, size_t *len)
+static int security_read_selinux_policy(struct selinux_state *state,
+					void **data, size_t *len)
 {
 	struct policydb *policydb = &state->ss->policydb;
 	int rc;
@@ -3736,12 +3748,6 @@ int security_read_policy(struct selinux_state *state,
 	if (!selinux_initialized(state))
 		return -EINVAL;
 
-	*len = security_policydb_len(state);
-
-	*data = vmalloc_user(*len);
-	if (!*data)
-		return -ENOMEM;
-
 	fp.data = *data;
 	fp.len = *len;
 
@@ -3754,5 +3760,52 @@ int security_read_policy(struct selinux_state *state,
 
 	*len = (unsigned long)fp.data - (unsigned long)*data;
 	return 0;
+}
+
+/**
+ * security_read_policy - read the policy.
+ * @data: binary policy data
+ * @len: length of data in bytes
+ *
+ */
+int security_read_policy(struct selinux_state *state,
+			 void **data, size_t *len)
+{
+	int rc;
+
+	rc = security_read_policy_len(state, len);
+	if (rc)
+		return rc;
+
+	*data = vmalloc_user(*len);
+	if (!*data)
+		return -ENOMEM;
+
+	return security_read_selinux_policy(state, data, len);
+}
+
+/**
+ * security_read_policy_kernel - read the policy.
+ * @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
+ *
+ */
+int security_read_policy_kernel(struct selinux_state *state,
+				void **data, size_t *len)
+{
+	int rc;
+
+	rc = security_read_policy_len(state, len);
+	if (rc)
+		return rc;
+
+	*data = vmalloc(*len);
+	if (!*data)
+		return -ENOMEM;
 
+	return security_read_selinux_policy(state, data, len);
 }
-- 
2.27.0


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

* [PATCH v5 4/4] IMA: Handle early boot data measurement
  2020-07-30  3:47 [PATCH v5 0/4] LSM: Measure security module data Lakshmi Ramasubramanian
                   ` (2 preceding siblings ...)
  2020-07-30  3:47 ` [PATCH v5 3/4] LSM: Define SELinux function to measure " Lakshmi Ramasubramanian
@ 2020-07-30  3:47 ` Lakshmi Ramasubramanian
  2020-07-30 18:02   ` Lakshmi Ramasubramanian
  3 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30  3:47 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

The current implementation of early boot measurement in
the IMA subsystem is very specific to asymmetric keys. It does not
handle measurement of other data such as Linux Security Module (LSM)
data. Since most security modules are initialized very early in
the boot cycle, data provided by those modules are not measured
by IMA. Any other subsystem that initializes early in the boot cycle
and needs IMA to measure their data would suffer from the same issue.

Update the early boot key measurement to handle any early boot data.
Change the kernel configuration CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS to
CONFIG_IMA_QUEUE_EARLY_BOOT_DATA so it can be used for enabling
early boot data measurement. Change this new configuration to support
SECURITY subsystem in addition to KEYS subsystem, which is currently
supported. This can be extended to include more subsystems in the future
by updating this kernel configuration.

Update LSM hooks namely ima_measure_lsm_state() and ima_measure_lsm_policy
to utilize early boot measurement support.

Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
---
 security/integrity/ima/Kconfig               |   5 +-
 security/integrity/ima/Makefile              |   2 +-
 security/integrity/ima/ima.h                 |  37 ++--
 security/integrity/ima/ima_asymmetric_keys.c |   6 +-
 security/integrity/ima/ima_init.c            |   2 +-
 security/integrity/ima/ima_main.c            |  22 ++-
 security/integrity/ima/ima_policy.c          |   2 +-
 security/integrity/ima/ima_queue_data.c      | 175 +++++++++++++++++++
 security/integrity/ima/ima_queue_keys.c      | 174 ------------------
 9 files changed, 223 insertions(+), 202 deletions(-)
 create mode 100644 security/integrity/ima/ima_queue_data.c
 delete mode 100644 security/integrity/ima/ima_queue_keys.c

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 080c53545ff0..86cba844f73c 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -322,10 +322,9 @@ config IMA_MEASURE_ASYMMETRIC_KEYS
 	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
 	default y
 
-config IMA_QUEUE_EARLY_BOOT_KEYS
+config IMA_QUEUE_EARLY_BOOT_DATA
 	bool
-	depends on IMA_MEASURE_ASYMMETRIC_KEYS
-	depends on SYSTEM_TRUSTED_KEYRING
+	depends on SECURITY || (IMA_MEASURE_ASYMMETRIC_KEYS && SYSTEM_TRUSTED_KEYRING)
 	default y
 
 config IMA_SECURE_AND_OR_TRUSTED_BOOT
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 67dabca670e2..cbbbc9848d2f 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -13,4 +13,4 @@ ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
 ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
 ima-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
 ima-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o
-ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o
+ima-$(CONFIG_IMA_QUEUE_EARLY_BOOT_DATA) += ima_queue_data.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 8ed9f5e1dd40..ebe4d9bb2f2b 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -229,29 +229,34 @@ extern const char *const func_tokens[];
 
 struct modsig;
 
-#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS
+#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_DATA
 /*
- * To track keys that need to be measured.
+ * To track data that needs to be measured.
  */
-struct ima_key_entry {
+struct ima_data_entry {
 	struct list_head list;
 	void *payload;
 	size_t payload_len;
-	char *keyring_name;
+	const char *event_name;
+	const char *event_data;
+	enum ima_hooks func;
 };
-void ima_init_key_queue(void);
-bool ima_should_queue_key(void);
-bool ima_queue_key(struct key *keyring, const void *payload,
-		   size_t payload_len);
-void ima_process_queued_keys(void);
+void ima_init_data_queue(void);
+bool ima_should_queue_data(void);
+bool ima_queue_data(const char *event_name, const void *payload,
+		    size_t payload_len, const char *event_data,
+		    enum ima_hooks func);
+void ima_process_queued_data(void);
 #else
-static inline void ima_init_key_queue(void) {}
-static inline bool ima_should_queue_key(void) { return false; }
-static inline bool ima_queue_key(struct key *keyring,
-				 const void *payload,
-				 size_t payload_len) { return false; }
-static inline void ima_process_queued_keys(void) {}
-#endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
+static inline void ima_init_data_queue(void) {}
+static inline bool ima_should_queue_data(void) { return false; }
+static inline bool ima_queue_data(const char *event_name,
+				  const void *payload,
+				  size_t payload_len,
+				  const char *event_data,
+				  enum ima_hooks func) { return false; }
+static inline void ima_process_queued_data(void) {}
+#endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_DATA */
 
 /* LIM API function definitions */
 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
diff --git a/security/integrity/ima/ima_asymmetric_keys.c b/security/integrity/ima/ima_asymmetric_keys.c
index 1c68c500c26f..8f8431f8b096 100644
--- a/security/integrity/ima/ima_asymmetric_keys.c
+++ b/security/integrity/ima/ima_asymmetric_keys.c
@@ -37,8 +37,10 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
 	if (!payload || (payload_len == 0))
 		return;
 
-	if (ima_should_queue_key())
-		queued = ima_queue_key(keyring, payload, payload_len);
+	if (ima_should_queue_data())
+		queued = ima_queue_data(keyring->description, payload,
+					payload_len, keyring->description,
+					KEY_CHECK);
 
 	if (queued)
 		return;
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 4902fe7bd570..892894bf4af3 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -145,7 +145,7 @@ int __init ima_init(void)
 	if (rc != 0)
 		return rc;
 
-	ima_init_key_queue();
+	ima_init_data_queue();
 
 	return rc;
 }
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 74d421e40c8f..1c4e140964df 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -846,6 +846,22 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
 	fdput(f);
 }
 
+static int ima_measure_lsm_data(const char *event_name,
+				const void *buf, int size,
+				enum ima_hooks func)
+{
+	bool queued = false;
+
+	if (ima_should_queue_data())
+		queued = ima_queue_data(event_name, buf, size, NULL, func);
+
+	if (queued)
+		return 0;
+
+	return process_buffer_measurement(NULL, buf, size, event_name, func,
+					  0, NULL);
+}
+
 /**
  * ima_measure_lsm_state - measure LSM specific state
  * @lsm_event_name: LSM event
@@ -860,8 +876,7 @@ int ima_measure_lsm_state(const char *lsm_event_name, const void *buf,
 	if (!lsm_event_name || !buf || !size)
 		return -EINVAL;
 
-	return process_buffer_measurement(NULL, buf, size, lsm_event_name,
-					  LSM_STATE, 0, NULL);
+	return ima_measure_lsm_data(lsm_event_name, buf, size, LSM_STATE);
 }
 
 /**
@@ -878,8 +893,7 @@ int ima_measure_lsm_policy(const char *lsm_event_name, const void *buf,
 	if (!lsm_event_name || !buf || !size)
 		return -EINVAL;
 
-	return process_buffer_measurement(NULL, buf, size, lsm_event_name,
-					  LSM_POLICY, 0, NULL);
+	return ima_measure_lsm_data(lsm_event_name, buf, size, LSM_POLICY);
 }
 
 static int __init init_ima(void)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index a0f5c39d9084..a8bfbca894ff 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -836,7 +836,7 @@ void ima_update_policy(void)
 	ima_update_policy_flag();
 
 	/* Custom IMA policy has been loaded */
-	ima_process_queued_keys();
+	ima_process_queued_data();
 }
 
 /* Keep the enumeration in sync with the policy_tokens! */
diff --git a/security/integrity/ima/ima_queue_data.c b/security/integrity/ima/ima_queue_data.c
new file mode 100644
index 000000000000..5eabd025ac2b
--- /dev/null
+++ b/security/integrity/ima/ima_queue_data.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Microsoft Corporation
+ *
+ * Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
+ *
+ * File: ima_queue_data.c
+ *       Enables deferred processing of data to be measured
+ */
+
+#include <linux/workqueue.h>
+#include "ima.h"
+
+/*
+ * Flag to indicate whether data can be processed
+ * right away or should be queued for processing later.
+ */
+static bool ima_process_data;
+
+/*
+ * To synchronize access to the list of data that need to be measured
+ */
+static DEFINE_MUTEX(ima_data_lock);
+static LIST_HEAD(ima_queued_data);
+
+/*
+ * If custom IMA policy is not loaded then data queued up
+ * for measurement should be freed. This worker is used
+ * for handling this scenario.
+ */
+static long ima_data_queue_timeout = 300000; /* 5 Minutes */
+static void ima_data_handler(struct work_struct *work);
+static DECLARE_DELAYED_WORK(ima_data_delayed_work, ima_data_handler);
+static bool timer_expired;
+
+/*
+ * This worker function frees data that may still be
+ * queued up in case custom IMA policy was not loaded.
+ */
+static void ima_data_handler(struct work_struct *work)
+{
+	timer_expired = true;
+	ima_process_queued_data();
+}
+
+/*
+ * This function sets up a worker to free queued data in case
+ * custom IMA policy was never loaded.
+ */
+void ima_init_data_queue(void)
+{
+	schedule_delayed_work(&ima_data_delayed_work,
+			      msecs_to_jiffies(ima_data_queue_timeout));
+}
+
+static void ima_free_data_entry(struct ima_data_entry *entry)
+{
+	if (!entry)
+		return;
+
+	kfree(entry->payload);
+	kfree(entry->event_name);
+	kfree(entry->event_data);
+	kfree(entry);
+}
+
+static struct ima_data_entry *ima_alloc_data_entry(const char *event_name,
+						   const void *payload,
+						   size_t payload_len,
+						   const char *event_data,
+						   enum ima_hooks func)
+{
+	struct ima_data_entry *entry;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		goto out;
+
+	entry->payload = kmemdup(payload, payload_len, GFP_KERNEL);
+	entry->event_name = kstrdup(event_name, GFP_KERNEL);
+	if (event_data)
+		entry->event_data = kstrdup(event_data, GFP_KERNEL);
+
+	entry->payload_len = payload_len;
+	entry->func = func;
+
+	if (!entry->payload || !entry->event_name ||
+		(event_data && !entry->event_data))
+		goto out;
+
+	INIT_LIST_HEAD(&entry->list);
+	return entry;
+
+out:
+	integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL,
+				event_name, func_measure_str(func),
+				"ENOMEM", -ENOMEM, 0, -ENOMEM);
+	ima_free_data_entry(entry);
+	return NULL;
+}
+
+bool ima_queue_data(const char *event_name, const void *payload,
+		    size_t payload_len, const char *event_data,
+		    enum ima_hooks func)
+{
+	bool queued = false;
+	struct ima_data_entry *entry;
+
+	entry = ima_alloc_data_entry(event_name, payload, payload_len,
+				     event_data, func);
+	if (!entry)
+		return false;
+
+	mutex_lock(&ima_data_lock);
+	if (!ima_process_data) {
+		list_add_tail(&entry->list, &ima_queued_data);
+		queued = true;
+	}
+	mutex_unlock(&ima_data_lock);
+
+	if (!queued)
+		ima_free_data_entry(entry);
+
+	return queued;
+}
+
+/*
+ * ima_process_queued_data() - process data queued for measurement
+ *
+ * This function sets ima_process_data to true and processes queued data.
+ * From here on data will be processed right away (not queued).
+ */
+void ima_process_queued_data(void)
+{
+	struct ima_data_entry *entry, *tmp;
+	bool process = false;
+
+	if (ima_process_data)
+		return;
+
+	/*
+	 * Since ima_process_data is set to true, any new data will be
+	 * processed immediately and not be queued to ima_queued_data list.
+	 * First one setting the ima_process_data flag to true will
+	 * process the queued data.
+	 */
+	mutex_lock(&ima_data_lock);
+	if (!ima_process_data) {
+		ima_process_data = true;
+		process = true;
+	}
+	mutex_unlock(&ima_data_lock);
+
+	if (!process)
+		return;
+
+	if (!timer_expired)
+		cancel_delayed_work_sync(&ima_data_delayed_work);
+
+	list_for_each_entry_safe(entry, tmp, &ima_queued_data, list) {
+		if (!timer_expired)
+			process_buffer_measurement(NULL, entry->payload,
+						   entry->payload_len,
+						   entry->event_name,
+						   entry->func, 0,
+						   entry->event_data);
+		list_del(&entry->list);
+		ima_free_data_entry(entry);
+	}
+}
+
+inline bool ima_should_queue_data(void)
+{
+	return !ima_process_data;
+}
diff --git a/security/integrity/ima/ima_queue_keys.c b/security/integrity/ima/ima_queue_keys.c
deleted file mode 100644
index 69a8626a35c0..000000000000
--- a/security/integrity/ima/ima_queue_keys.c
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2019 Microsoft Corporation
- *
- * Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
- *
- * File: ima_queue_keys.c
- *       Enables deferred processing of keys
- */
-
-#include <linux/workqueue.h>
-#include <keys/asymmetric-type.h>
-#include "ima.h"
-
-/*
- * Flag to indicate whether a key can be processed
- * right away or should be queued for processing later.
- */
-static bool ima_process_keys;
-
-/*
- * To synchronize access to the list of keys that need to be measured
- */
-static DEFINE_MUTEX(ima_keys_lock);
-static LIST_HEAD(ima_keys);
-
-/*
- * If custom IMA policy is not loaded then keys queued up
- * for measurement should be freed. This worker is used
- * for handling this scenario.
- */
-static long ima_key_queue_timeout = 300000; /* 5 Minutes */
-static void ima_keys_handler(struct work_struct *work);
-static DECLARE_DELAYED_WORK(ima_keys_delayed_work, ima_keys_handler);
-static bool timer_expired;
-
-/*
- * This worker function frees keys that may still be
- * queued up in case custom IMA policy was not loaded.
- */
-static void ima_keys_handler(struct work_struct *work)
-{
-	timer_expired = true;
-	ima_process_queued_keys();
-}
-
-/*
- * This function sets up a worker to free queued keys in case
- * custom IMA policy was never loaded.
- */
-void ima_init_key_queue(void)
-{
-	schedule_delayed_work(&ima_keys_delayed_work,
-			      msecs_to_jiffies(ima_key_queue_timeout));
-}
-
-static void ima_free_key_entry(struct ima_key_entry *entry)
-{
-	if (entry) {
-		kfree(entry->payload);
-		kfree(entry->keyring_name);
-		kfree(entry);
-	}
-}
-
-static struct ima_key_entry *ima_alloc_key_entry(struct key *keyring,
-						 const void *payload,
-						 size_t payload_len)
-{
-	int rc = 0;
-	const char *audit_cause = "ENOMEM";
-	struct ima_key_entry *entry;
-
-	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-	if (entry) {
-		entry->payload = kmemdup(payload, payload_len, GFP_KERNEL);
-		entry->keyring_name = kstrdup(keyring->description,
-					      GFP_KERNEL);
-		entry->payload_len = payload_len;
-	}
-
-	if ((entry == NULL) || (entry->payload == NULL) ||
-	    (entry->keyring_name == NULL)) {
-		rc = -ENOMEM;
-		goto out;
-	}
-
-	INIT_LIST_HEAD(&entry->list);
-
-out:
-	if (rc) {
-		integrity_audit_message(AUDIT_INTEGRITY_PCR, NULL,
-					keyring->description,
-					func_measure_str(KEY_CHECK),
-					audit_cause, rc, 0, rc);
-		ima_free_key_entry(entry);
-		entry = NULL;
-	}
-
-	return entry;
-}
-
-bool ima_queue_key(struct key *keyring, const void *payload,
-		   size_t payload_len)
-{
-	bool queued = false;
-	struct ima_key_entry *entry;
-
-	entry = ima_alloc_key_entry(keyring, payload, payload_len);
-	if (!entry)
-		return false;
-
-	mutex_lock(&ima_keys_lock);
-	if (!ima_process_keys) {
-		list_add_tail(&entry->list, &ima_keys);
-		queued = true;
-	}
-	mutex_unlock(&ima_keys_lock);
-
-	if (!queued)
-		ima_free_key_entry(entry);
-
-	return queued;
-}
-
-/*
- * ima_process_queued_keys() - process keys queued for measurement
- *
- * This function sets ima_process_keys to true and processes queued keys.
- * From here on keys will be processed right away (not queued).
- */
-void ima_process_queued_keys(void)
-{
-	struct ima_key_entry *entry, *tmp;
-	bool process = false;
-
-	if (ima_process_keys)
-		return;
-
-	/*
-	 * Since ima_process_keys is set to true, any new key will be
-	 * processed immediately and not be queued to ima_keys list.
-	 * First one setting the ima_process_keys flag to true will
-	 * process the queued keys.
-	 */
-	mutex_lock(&ima_keys_lock);
-	if (!ima_process_keys) {
-		ima_process_keys = true;
-		process = true;
-	}
-	mutex_unlock(&ima_keys_lock);
-
-	if (!process)
-		return;
-
-	if (!timer_expired)
-		cancel_delayed_work_sync(&ima_keys_delayed_work);
-
-	list_for_each_entry_safe(entry, tmp, &ima_keys, list) {
-		if (!timer_expired)
-			process_buffer_measurement(NULL, entry->payload,
-						   entry->payload_len,
-						   entry->keyring_name,
-						   KEY_CHECK, 0,
-						   entry->keyring_name);
-		list_del(&entry->list);
-		ima_free_key_entry(entry);
-	}
-}
-
-inline bool ima_should_queue_key(void)
-{
-	return !ima_process_keys;
-}
-- 
2.27.0


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

* Re: [PATCH v5 1/4] IMA: Add func to measure LSM state and policy
  2020-07-30  3:47 ` [PATCH v5 1/4] IMA: Add func to measure LSM state and policy Lakshmi Ramasubramanian
@ 2020-07-30 15:02   ` Tyler Hicks
  2020-07-30 15:15     ` Lakshmi Ramasubramanian
  2020-07-30 16:19     ` Casey Schaufler
  0 siblings, 2 replies; 23+ messages in thread
From: Tyler Hicks @ 2020-07-30 15:02 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: zohar, stephen.smalley.work, casey, sashal, jmorris,
	linux-integrity, selinux, linux-security-module, linux-kernel

On 2020-07-29 20:47:21, Lakshmi Ramasubramanian wrote:
> Critical data structures of security modules need to be measured to
> enable an attestation service to verify if the configuration and
> policies for the security modules have been setup correctly and
> that they haven't been tampered with at runtime. A new IMA policy is
> required for handling this measurement.
> 
> Define two new IMA policy func namely LSM_STATE and LSM_POLICY to
> measure the state and the policy provided by the security modules.
> Update ima_match_rules() and ima_validate_rule() to check for
> the new func and ima_parse_rule() to handle the new func.
> 
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> ---
>  Documentation/ABI/testing/ima_policy |  9 ++++++++
>  security/integrity/ima/ima.h         |  2 ++
>  security/integrity/ima/ima_api.c     |  2 +-
>  security/integrity/ima/ima_policy.c  | 31 ++++++++++++++++++++++++----
>  4 files changed, 39 insertions(+), 5 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
> index cd572912c593..b7c7fb548c0c 100644
> --- a/Documentation/ABI/testing/ima_policy
> +++ b/Documentation/ABI/testing/ima_policy
> @@ -30,6 +30,7 @@ Description:
>  				[FIRMWARE_CHECK]
>  				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
>  				[KEXEC_CMDLINE] [KEY_CHECK]
> +				[LSM_STATE] [LSM_POLICY]
>  			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
>  			       [[^]MAY_EXEC]
>  			fsmagic:= hex value
> @@ -125,3 +126,11 @@ Description:
>  		keys added to .builtin_trusted_keys or .ima keyring:
>  
>  			measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima
> +
> +		Example of measure rule using LSM_STATE to measure LSM state:
> +
> +			measure func=LSM_STATE template=ima-buf
> +
> +		Example of measure rule using LSM_POLICY to measure LSM policy:
> +
> +			measure func=LSM_POLICY template=ima-ng
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 38043074ce5e..1b5f4b2f17d0 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -200,6 +200,8 @@ static inline unsigned int ima_hash_key(u8 *digest)
>  	hook(POLICY_CHECK, policy)			\
>  	hook(KEXEC_CMDLINE, kexec_cmdline)		\
>  	hook(KEY_CHECK, key)				\
> +	hook(LSM_STATE, lsm_state)			\
> +	hook(LSM_POLICY, lsm_policy)			\
>  	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 4f39fb93f278..8c8b4e4a6493 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 | LSM_STATE | LSM_POLICY
>   *	mask: contains the permission mask
>   *	fsmagic: hex value
>   *
> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> index 07f033634b27..a0f5c39d9084 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -442,13 +442,20 @@ 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_keyring(rule, keyring, cred);
> -	}
>  	if ((rule->flags & IMA_FUNC) &&
>  	    (rule->func != func && func != POST_SETATTR))
>  		return false;
> +
> +	switch (func) {
> +	case KEY_CHECK:
> +		return ima_match_keyring(rule, keyring, cred);
> +	case LSM_STATE:
> +	case LSM_POLICY:
> +		return true;
> +	default:
> +		break;
> +	}
> +
>  	if ((rule->flags & IMA_MASK) &&
>  	    (rule->mask != mask && func != POST_SETATTR))
>  		return false;
> @@ -1044,6 +1051,18 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>  		if (ima_rule_contains_lsm_cond(entry))
>  			return false;
>  
> +		break;
> +	case LSM_STATE:
> +	case LSM_POLICY:
> +		if (entry->action & ~(MEASURE | DONT_MEASURE))
> +			return false;
> +
> +		if (entry->flags & ~(IMA_FUNC | IMA_PCR))
> +			return false;
> +
> +		if (ima_rule_contains_lsm_cond(entry))
> +			return false;
> +
>  		break;
>  	default:
>  		return false;
> @@ -1176,6 +1195,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>  				entry->func = KEXEC_CMDLINE;
>  			else if (strcmp(args[0].from, "KEY_CHECK") == 0)
>  				entry->func = KEY_CHECK;
> +			else if (strcmp(args[0].from, "LSM_STATE") == 0)
> +				entry->func = LSM_STATE;
> +			else if (strcmp(args[0].from, "LSM_POLICY") == 0)
> +				entry->func = LSM_POLICY;

This patch generally looks really good to me with the exception of one
thing...

We should only accept rules with these specified hook functions when an
LSM that has measurement support is enabled. This messes up the ordering
of your patch series but it could be as simple as doing this:

			else if (IS_ENABLED(CONFIG_SECURITY_SELINUX) &&
				 strcmp(args[0].from, "LSM_STATE") == 0)
				 entry->func = LSM_STATE;

Or you could do something a little more complex, like what's done with
CONFIG_IMA_LSM_RULES. You could create a CONFIG_IMA_MEASURE_LSM option
that's default enabled but depends on CONFIG_SECURITY_SELINUX and then
check for IS_ENABLED(CONFIG_IMA_MEASURE_LSM) in ima_parse_rule().

I'd personally opt for just placing the
IS_ENABLED(CONFIG_SECURITY_SELINUX) check directly into
ima_parse_rule().

Tyler

>  			else
>  				result = -EINVAL;
>  			if (!result)
> -- 
> 2.27.0

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

* Re: [PATCH v5 2/4] IMA: Define IMA hooks to measure LSM state and policy
  2020-07-30  3:47 ` [PATCH v5 2/4] IMA: Define IMA hooks " Lakshmi Ramasubramanian
@ 2020-07-30 15:04   ` Tyler Hicks
  0 siblings, 0 replies; 23+ messages in thread
From: Tyler Hicks @ 2020-07-30 15:04 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: zohar, stephen.smalley.work, casey, sashal, jmorris,
	linux-integrity, selinux, linux-security-module, linux-kernel

On 2020-07-29 20:47:22, Lakshmi Ramasubramanian wrote:
> IMA subsystem needs to define IMA hooks that the security modules can
> call to measure state and policy data.
> 
> Define two new IMA hooks, namely ima_lsm_state() and ima_lsm_policy(),
> that the security modules can call to measure LSM state and LSM policy
> respectively. Return the status of the measurement operation from these
> two IMA hooks.
> 
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>

Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>

Tyler

> ---
>  include/linux/ima.h               | 14 +++++++++
>  security/integrity/ima/ima.h      |  6 ++--
>  security/integrity/ima/ima_main.c | 50 ++++++++++++++++++++++++++-----
>  3 files changed, 60 insertions(+), 10 deletions(-)
> 
> diff --git a/include/linux/ima.h b/include/linux/ima.h
> index d15100de6cdd..442ca0dce3c8 100644
> --- a/include/linux/ima.h
> +++ b/include/linux/ima.h
> @@ -26,6 +26,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 int ima_measure_lsm_state(const char *lsm_event_name, const void *buf,
> +				 int size);
> +extern int ima_measure_lsm_policy(const char *lsm_event_name, const void *buf,
> +				  int size);
>  
>  #ifdef CONFIG_IMA_KEXEC
>  extern void ima_add_kexec_buffer(struct kimage *image);
> @@ -104,6 +108,16 @@ 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 int ima_measure_lsm_state(const char *lsm_event_name,
> +					const void *buf, int size)
> +{
> +	return -EOPNOTSUPP;
> +}
> +static inline int ima_measure_lsm_policy(const char *lsm_event_name,
> +					 const void *buf, int size)
> +{
> +	return -EOPNOTSUPP;
> +}
>  #endif /* CONFIG_IMA */
>  
>  #ifndef CONFIG_IMA_KEXEC
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 1b5f4b2f17d0..8ed9f5e1dd40 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -267,9 +267,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
>  			   struct evm_ima_xattr_data *xattr_value,
>  			   int xattr_len, const struct modsig *modsig, int pcr,
>  			   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 process_buffer_measurement(struct inode *inode, const void *buf, int size,
> +			       const char *eventname, enum ima_hooks func,
> +			       int pcr, const char *keyring);
>  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_main.c b/security/integrity/ima/ima_main.c
> index 8a91711ca79b..74d421e40c8f 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -736,9 +736,9 @@ int ima_load_data(enum kernel_load_data_id id)
>   *
>   * 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 process_buffer_measurement(struct inode *inode, const void *buf, int size,
> +			       const char *eventname, enum ima_hooks func,
> +			       int pcr, const char *keyring)
>  {
>  	int ret = 0;
>  	const char *audit_cause = "ENOMEM";
> @@ -758,7 +758,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>  	u32 secid;
>  
>  	if (!ima_policy_flag)
> -		return;
> +		return 0;
>  
>  	/*
>  	 * Both LSM hooks and auxilary based buffer measurements are
> @@ -772,7 +772,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>  		action = ima_get_action(inode, current_cred(), secid, 0, func,
>  					&pcr, &template, keyring);
>  		if (!(action & IMA_MEASURE))
> -			return;
> +			return 0;
>  	}
>  
>  	if (!pcr)
> @@ -787,7 +787,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>  			pr_err("template %s init failed, result: %d\n",
>  			       (strlen(template->name) ?
>  				template->name : template->fmt), ret);
> -			return;
> +			return ret;
>  		}
>  	}
>  
> @@ -819,7 +819,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
>  					func_measure_str(func),
>  					audit_cause, ret, 0, ret);
>  
> -	return;
> +	return ret;
>  }
>  
>  /**
> @@ -846,6 +846,42 @@ void ima_kexec_cmdline(int kernel_fd, const void *buf, int size)
>  	fdput(f);
>  }
>  
> +/**
> + * ima_measure_lsm_state - measure LSM specific state
> + * @lsm_event_name: LSM event
> + * @buf: pointer to buffer containing LSM specific state
> + * @size: Number of bytes in buf
> + *
> + * Buffers can only be measured, not appraised.
> + */
> +int ima_measure_lsm_state(const char *lsm_event_name, const void *buf,
> +			  int size)
> +{
> +	if (!lsm_event_name || !buf || !size)
> +		return -EINVAL;
> +
> +	return process_buffer_measurement(NULL, buf, size, lsm_event_name,
> +					  LSM_STATE, 0, NULL);
> +}
> +
> +/**
> + * ima_measure_lsm_policy - measure LSM specific policy
> + * @lsm_event_name: LSM event
> + * @buf: pointer to buffer containing LSM specific policy
> + * @size: Number of bytes in buf
> + *
> + * Buffers can only be measured, not appraised.
> + */
> +int ima_measure_lsm_policy(const char *lsm_event_name, const void *buf,
> +			   int size)
> +{
> +	if (!lsm_event_name || !buf || !size)
> +		return -EINVAL;
> +
> +	return process_buffer_measurement(NULL, buf, size, lsm_event_name,
> +					  LSM_POLICY, 0, NULL);
> +}
> +
>  static int __init init_ima(void)
>  {
>  	int error;
> -- 
> 2.27.0

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

* Re: [PATCH v5 1/4] IMA: Add func to measure LSM state and policy
  2020-07-30 15:02   ` Tyler Hicks
@ 2020-07-30 15:15     ` Lakshmi Ramasubramanian
  2020-07-30 15:17       ` Tyler Hicks
  2020-07-30 16:19     ` Casey Schaufler
  1 sibling, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30 15:15 UTC (permalink / raw)
  To: Tyler Hicks
  Cc: zohar, stephen.smalley.work, casey, sashal, jmorris,
	linux-integrity, selinux, linux-security-module, linux-kernel

On 7/30/20 8:02 AM, Tyler Hicks wrote:

>> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
>> index 07f033634b27..a0f5c39d9084 100644
>> --- a/security/integrity/ima/ima_policy.c
>> +++ b/security/integrity/ima/ima_policy.c
>> @@ -442,13 +442,20 @@ 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_keyring(rule, keyring, cred);
>> -	}
>>   	if ((rule->flags & IMA_FUNC) &&
>>   	    (rule->func != func && func != POST_SETATTR))
>>   		return false;
>> +
>> +	switch (func) {
>> +	case KEY_CHECK:
>> +		return ima_match_keyring(rule, keyring, cred);
>> +	case LSM_STATE:
>> +	case LSM_POLICY:
>> +		return true;
>> +	default:
>> +		break;
>> +	}
>> +
>>   	if ((rule->flags & IMA_MASK) &&
>>   	    (rule->mask != mask && func != POST_SETATTR))
>>   		return false;
>> @@ -1044,6 +1051,18 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>>   		if (ima_rule_contains_lsm_cond(entry))
>>   			return false;
>>   
>> +		break;
>> +	case LSM_STATE:
>> +	case LSM_POLICY:
>> +		if (entry->action & ~(MEASURE | DONT_MEASURE))
>> +			return false;
>> +
>> +		if (entry->flags & ~(IMA_FUNC | IMA_PCR))
>> +			return false;
>> +
>> +		if (ima_rule_contains_lsm_cond(entry))
>> +			return false;
>> +
>>   		break;
>>   	default:
>>   		return false;
>> @@ -1176,6 +1195,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>>   				entry->func = KEXEC_CMDLINE;
>>   			else if (strcmp(args[0].from, "KEY_CHECK") == 0)
>>   				entry->func = KEY_CHECK;
>> +			else if (strcmp(args[0].from, "LSM_STATE") == 0)
>> +				entry->func = LSM_STATE;
>> +			else if (strcmp(args[0].from, "LSM_POLICY") == 0)
>> +				entry->func = LSM_POLICY;
> 
> This patch generally looks really good to me with the exception of one
> thing...
> 
> We should only accept rules with these specified hook functions when an
> LSM that has measurement support is enabled. This messes up the ordering
> of your patch series but it could be as simple as doing this:
> 
> 			else if (IS_ENABLED(CONFIG_SECURITY_SELINUX) &&
> 				 strcmp(args[0].from, "LSM_STATE") == 0)
> 				 entry->func = LSM_STATE;
> 
> Or you could do something a little more complex, like what's done with
> CONFIG_IMA_LSM_RULES. You could create a CONFIG_IMA_MEASURE_LSM option
> that's default enabled but depends on CONFIG_SECURITY_SELINUX and then
> check for IS_ENABLED(CONFIG_IMA_MEASURE_LSM) in ima_parse_rule().
> 
> I'd personally opt for just placing the
> IS_ENABLED(CONFIG_SECURITY_SELINUX) check directly into
> ima_parse_rule().
> 

The LSM hook can be used by any security module (not just SELinux) to 
measure their data.

I have implemented measurement in SELinux to illustrate the usage. 
Maybe, I can add the check you have suggested for now and when more 
security modules start using this IMA policy additional checks can be 
added as appropriate.

thanks,
  -lakshmi


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

* Re: [PATCH v5 1/4] IMA: Add func to measure LSM state and policy
  2020-07-30 15:15     ` Lakshmi Ramasubramanian
@ 2020-07-30 15:17       ` Tyler Hicks
  0 siblings, 0 replies; 23+ messages in thread
From: Tyler Hicks @ 2020-07-30 15:17 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: zohar, stephen.smalley.work, casey, sashal, jmorris,
	linux-integrity, selinux, linux-security-module, linux-kernel

On 2020-07-30 08:15:34, Lakshmi Ramasubramanian wrote:
> On 7/30/20 8:02 AM, Tyler Hicks wrote:
> 
> > > diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
> > > index 07f033634b27..a0f5c39d9084 100644
> > > --- a/security/integrity/ima/ima_policy.c
> > > +++ b/security/integrity/ima/ima_policy.c
> > > @@ -442,13 +442,20 @@ 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_keyring(rule, keyring, cred);
> > > -	}
> > >   	if ((rule->flags & IMA_FUNC) &&
> > >   	    (rule->func != func && func != POST_SETATTR))
> > >   		return false;
> > > +
> > > +	switch (func) {
> > > +	case KEY_CHECK:
> > > +		return ima_match_keyring(rule, keyring, cred);
> > > +	case LSM_STATE:
> > > +	case LSM_POLICY:
> > > +		return true;
> > > +	default:
> > > +		break;
> > > +	}
> > > +
> > >   	if ((rule->flags & IMA_MASK) &&
> > >   	    (rule->mask != mask && func != POST_SETATTR))
> > >   		return false;
> > > @@ -1044,6 +1051,18 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
> > >   		if (ima_rule_contains_lsm_cond(entry))
> > >   			return false;
> > > +		break;
> > > +	case LSM_STATE:
> > > +	case LSM_POLICY:
> > > +		if (entry->action & ~(MEASURE | DONT_MEASURE))
> > > +			return false;
> > > +
> > > +		if (entry->flags & ~(IMA_FUNC | IMA_PCR))
> > > +			return false;
> > > +
> > > +		if (ima_rule_contains_lsm_cond(entry))
> > > +			return false;
> > > +
> > >   		break;
> > >   	default:
> > >   		return false;
> > > @@ -1176,6 +1195,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
> > >   				entry->func = KEXEC_CMDLINE;
> > >   			else if (strcmp(args[0].from, "KEY_CHECK") == 0)
> > >   				entry->func = KEY_CHECK;
> > > +			else if (strcmp(args[0].from, "LSM_STATE") == 0)
> > > +				entry->func = LSM_STATE;
> > > +			else if (strcmp(args[0].from, "LSM_POLICY") == 0)
> > > +				entry->func = LSM_POLICY;
> > 
> > This patch generally looks really good to me with the exception of one
> > thing...
> > 
> > We should only accept rules with these specified hook functions when an
> > LSM that has measurement support is enabled. This messes up the ordering
> > of your patch series but it could be as simple as doing this:
> > 
> > 			else if (IS_ENABLED(CONFIG_SECURITY_SELINUX) &&
> > 				 strcmp(args[0].from, "LSM_STATE") == 0)
> > 				 entry->func = LSM_STATE;
> > 
> > Or you could do something a little more complex, like what's done with
> > CONFIG_IMA_LSM_RULES. You could create a CONFIG_IMA_MEASURE_LSM option
> > that's default enabled but depends on CONFIG_SECURITY_SELINUX and then
> > check for IS_ENABLED(CONFIG_IMA_MEASURE_LSM) in ima_parse_rule().
> > 
> > I'd personally opt for just placing the
> > IS_ENABLED(CONFIG_SECURITY_SELINUX) check directly into
> > ima_parse_rule().
> > 
> 
> The LSM hook can be used by any security module (not just SELinux) to
> measure their data.
> 
> I have implemented measurement in SELinux to illustrate the usage. Maybe, I
> can add the check you have suggested for now and when more security modules
> start using this IMA policy additional checks can be added as appropriate.

Yes, that's what I envision.

The main idea is that there's negative feedback to userspace when IMA
can't possibly do anything with an LSM_STATE/LSM_POLICY rule.

Tyler

> 
> thanks,
>  -lakshmi

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

* Re: [PATCH v5 1/4] IMA: Add func to measure LSM state and policy
  2020-07-30 15:02   ` Tyler Hicks
  2020-07-30 15:15     ` Lakshmi Ramasubramanian
@ 2020-07-30 16:19     ` Casey Schaufler
  2020-07-30 16:33       ` Lakshmi Ramasubramanian
  1 sibling, 1 reply; 23+ messages in thread
From: Casey Schaufler @ 2020-07-30 16:19 UTC (permalink / raw)
  To: Tyler Hicks, Lakshmi Ramasubramanian
  Cc: zohar, stephen.smalley.work, sashal, jmorris, linux-integrity,
	selinux, linux-security-module, linux-kernel, Casey Schaufler

On 7/30/2020 8:02 AM, Tyler Hicks wrote:
> On 2020-07-29 20:47:21, Lakshmi Ramasubramanian wrote:
>> Critical data structures of security modules need to be measured to
>> enable an attestation service to verify if the configuration and
>> policies for the security modules have been setup correctly and
>> that they haven't been tampered with at runtime. A new IMA policy is
>> required for handling this measurement.
>>
>> Define two new IMA policy func namely LSM_STATE and LSM_POLICY to
>> measure the state and the policy provided by the security modules.

If, as you suggest below, this is SELinux specific,
these should be SELINUX_STATE and SELINUX_POLICY.
It makes me very uncomfortable when I see LSM used
in cases where SELinux is required. The LSM is supposed
to be an agnostic interface, so if you need to throw

	if (IS_ENABLED(CONFIG_SECURITY_SELINUX) &&

into the IMA code you're clearly not thinking in terms
of the LSM layer. I have no problem with seeing SELinux
oriented and/or specific code in IMA if that's what you want.
Just don't call it LSM.

>> Update ima_match_rules() and ima_validate_rule() to check for
>> the new func and ima_parse_rule() to handle the new func.
>>
>> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
>> ---
>>  Documentation/ABI/testing/ima_policy |  9 ++++++++
>>  security/integrity/ima/ima.h         |  2 ++
>>  security/integrity/ima/ima_api.c     |  2 +-
>>  security/integrity/ima/ima_policy.c  | 31 ++++++++++++++++++++++++----
>>  4 files changed, 39 insertions(+), 5 deletions(-)
>>
>> diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
>> index cd572912c593..b7c7fb548c0c 100644
>> --- a/Documentation/ABI/testing/ima_policy
>> +++ b/Documentation/ABI/testing/ima_policy
>> @@ -30,6 +30,7 @@ Description:
>>  				[FIRMWARE_CHECK]
>>  				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
>>  				[KEXEC_CMDLINE] [KEY_CHECK]
>> +				[LSM_STATE] [LSM_POLICY]
>>  			mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
>>  			       [[^]MAY_EXEC]
>>  			fsmagic:= hex value
>> @@ -125,3 +126,11 @@ Description:
>>  		keys added to .builtin_trusted_keys or .ima keyring:
>>  
>>  			measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima
>> +
>> +		Example of measure rule using LSM_STATE to measure LSM state:
>> +
>> +			measure func=LSM_STATE template=ima-buf
>> +
>> +		Example of measure rule using LSM_POLICY to measure LSM policy:
>> +
>> +			measure func=LSM_POLICY template=ima-ng
>> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
>> index 38043074ce5e..1b5f4b2f17d0 100644
>> --- a/security/integrity/ima/ima.h
>> +++ b/security/integrity/ima/ima.h
>> @@ -200,6 +200,8 @@ static inline unsigned int ima_hash_key(u8 *digest)
>>  	hook(POLICY_CHECK, policy)			\
>>  	hook(KEXEC_CMDLINE, kexec_cmdline)		\
>>  	hook(KEY_CHECK, key)				\
>> +	hook(LSM_STATE, lsm_state)			\
>> +	hook(LSM_POLICY, lsm_policy)			\
>>  	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 4f39fb93f278..8c8b4e4a6493 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 | LSM_STATE | LSM_POLICY
>>   *	mask: contains the permission mask
>>   *	fsmagic: hex value
>>   *
>> diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
>> index 07f033634b27..a0f5c39d9084 100644
>> --- a/security/integrity/ima/ima_policy.c
>> +++ b/security/integrity/ima/ima_policy.c
>> @@ -442,13 +442,20 @@ 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_keyring(rule, keyring, cred);
>> -	}
>>  	if ((rule->flags & IMA_FUNC) &&
>>  	    (rule->func != func && func != POST_SETATTR))
>>  		return false;
>> +
>> +	switch (func) {
>> +	case KEY_CHECK:
>> +		return ima_match_keyring(rule, keyring, cred);
>> +	case LSM_STATE:
>> +	case LSM_POLICY:
>> +		return true;
>> +	default:
>> +		break;
>> +	}
>> +
>>  	if ((rule->flags & IMA_MASK) &&
>>  	    (rule->mask != mask && func != POST_SETATTR))
>>  		return false;
>> @@ -1044,6 +1051,18 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
>>  		if (ima_rule_contains_lsm_cond(entry))
>>  			return false;
>>  
>> +		break;
>> +	case LSM_STATE:
>> +	case LSM_POLICY:
>> +		if (entry->action & ~(MEASURE | DONT_MEASURE))
>> +			return false;
>> +
>> +		if (entry->flags & ~(IMA_FUNC | IMA_PCR))
>> +			return false;
>> +
>> +		if (ima_rule_contains_lsm_cond(entry))
>> +			return false;
>> +
>>  		break;
>>  	default:
>>  		return false;
>> @@ -1176,6 +1195,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
>>  				entry->func = KEXEC_CMDLINE;
>>  			else if (strcmp(args[0].from, "KEY_CHECK") == 0)
>>  				entry->func = KEY_CHECK;
>> +			else if (strcmp(args[0].from, "LSM_STATE") == 0)
>> +				entry->func = LSM_STATE;
>> +			else if (strcmp(args[0].from, "LSM_POLICY") == 0)
>> +				entry->func = LSM_POLICY;
> This patch generally looks really good to me with the exception of one
> thing...
>
> We should only accept rules with these specified hook functions when an
> LSM that has measurement support is enabled. This messes up the ordering
> of your patch series but it could be as simple as doing this:
>
> 			else if (IS_ENABLED(CONFIG_SECURITY_SELINUX) &&
> 				 strcmp(args[0].from, "LSM_STATE") == 0)
> 				 entry->func = LSM_STATE;
>
> Or you could do something a little more complex, like what's done with
> CONFIG_IMA_LSM_RULES. You could create a CONFIG_IMA_MEASURE_LSM option
> that's default enabled but depends on CONFIG_SECURITY_SELINUX and then
> check for IS_ENABLED(CONFIG_IMA_MEASURE_LSM) in ima_parse_rule().
>
> I'd personally opt for just placing the
> IS_ENABLED(CONFIG_SECURITY_SELINUX) check directly into
> ima_parse_rule().
>
> Tyler
>
>>  			else
>>  				result = -EINVAL;
>>  			if (!result)
>> -- 
>> 2.27.0

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

* Re: [PATCH v5 1/4] IMA: Add func to measure LSM state and policy
  2020-07-30 16:19     ` Casey Schaufler
@ 2020-07-30 16:33       ` Lakshmi Ramasubramanian
  0 siblings, 0 replies; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30 16:33 UTC (permalink / raw)
  To: Casey Schaufler, Tyler Hicks
  Cc: zohar, stephen.smalley.work, sashal, jmorris, linux-integrity,
	selinux, linux-security-module, linux-kernel

On 7/30/20 9:19 AM, Casey Schaufler wrote:

>>> Critical data structures of security modules need to be measured to
>>> enable an attestation service to verify if the configuration and
>>> policies for the security modules have been setup correctly and
>>> that they haven't been tampered with at runtime. A new IMA policy is
>>> required for handling this measurement.
>>>
>>> Define two new IMA policy func namely LSM_STATE and LSM_POLICY to
>>> measure the state and the policy provided by the security modules.
> 
> If, as you suggest below, this is SELinux specific,
> these should be SELINUX_STATE and SELINUX_POLICY.
> It makes me very uncomfortable when I see LSM used
> in cases where SELinux is required. The LSM is supposed
> to be an agnostic interface, so if you need to throw
> 
> 	if (IS_ENABLED(CONFIG_SECURITY_SELINUX) &&
> 
> into the IMA code you're clearly not thinking in terms
> of the LSM layer. I have no problem with seeing SELinux
> oriented and/or specific code in IMA if that's what you want.
> Just don't call it LSM.

The hook defined in IMA is not SELinux specific - it is generic enough 
to be used by any security module to measure their STATE and POLICY.

I have implemented the measurement for SELinux to illustrate the usage.

Tyler's suggestion was to allow this IMA policy only when component(s) 
that are using it are also enabled.

  -lakshmi



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

* Re: [PATCH v5 4/4] IMA: Handle early boot data measurement
  2020-07-30  3:47 ` [PATCH v5 4/4] IMA: Handle early boot data measurement Lakshmi Ramasubramanian
@ 2020-07-30 18:02   ` Lakshmi Ramasubramanian
  2020-07-30 20:04     ` Tyler Hicks
  0 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-07-30 18:02 UTC (permalink / raw)
  To: zohar, stephen.smalley.work, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

On 7/29/20 8:47 PM, Lakshmi Ramasubramanian wrote:

Hi Tyler,

> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index 080c53545ff0..86cba844f73c 100644
> --- a/security/integrity/ima/Kconfig
> +++ b/security/integrity/ima/Kconfig
> @@ -322,10 +322,9 @@ config IMA_MEASURE_ASYMMETRIC_KEYS
>   	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
>   	default y
>   
> -config IMA_QUEUE_EARLY_BOOT_KEYS
> +config IMA_QUEUE_EARLY_BOOT_DATA
>   	bool
> -	depends on IMA_MEASURE_ASYMMETRIC_KEYS
> -	depends on SYSTEM_TRUSTED_KEYRING
> +	depends on SECURITY || (IMA_MEASURE_ASYMMETRIC_KEYS && SYSTEM_TRUSTED_KEYRING)
>   	default y
>   
Similar to the change you'd suggested for validating LSM_STATE and 
LSM_POLICY func, I think IMA_QUEUE_EARLY_BOOT_DATA config should be 
enabled for SECURITY_SELINUX.

depends on SECURITY_SELINUX ||
            (IMA_MEASURE_ASYMMETRIC_KEYS && SYSTEM_TRUSTED_KEYRING)

And, when more security modules are added update this CONFIG as appropriate.

Does that sound okay?

  -lakshmi

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

* Re: [PATCH v5 4/4] IMA: Handle early boot data measurement
  2020-07-30 18:02   ` Lakshmi Ramasubramanian
@ 2020-07-30 20:04     ` Tyler Hicks
  0 siblings, 0 replies; 23+ messages in thread
From: Tyler Hicks @ 2020-07-30 20:04 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: zohar, stephen.smalley.work, casey, sashal, jmorris,
	linux-integrity, selinux, linux-security-module, linux-kernel

On 2020-07-30 11:02:50, Lakshmi Ramasubramanian wrote:
> On 7/29/20 8:47 PM, Lakshmi Ramasubramanian wrote:
> 
> Hi Tyler,
> 
> > diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> > index 080c53545ff0..86cba844f73c 100644
> > --- a/security/integrity/ima/Kconfig
> > +++ b/security/integrity/ima/Kconfig
> > @@ -322,10 +322,9 @@ config IMA_MEASURE_ASYMMETRIC_KEYS
> >   	depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
> >   	default y
> > -config IMA_QUEUE_EARLY_BOOT_KEYS
> > +config IMA_QUEUE_EARLY_BOOT_DATA
> >   	bool
> > -	depends on IMA_MEASURE_ASYMMETRIC_KEYS
> > -	depends on SYSTEM_TRUSTED_KEYRING
> > +	depends on SECURITY || (IMA_MEASURE_ASYMMETRIC_KEYS && SYSTEM_TRUSTED_KEYRING)
> >   	default y
> Similar to the change you'd suggested for validating LSM_STATE and
> LSM_POLICY func, I think IMA_QUEUE_EARLY_BOOT_DATA config should be enabled
> for SECURITY_SELINUX.
> 
> depends on SECURITY_SELINUX ||
>            (IMA_MEASURE_ASYMMETRIC_KEYS && SYSTEM_TRUSTED_KEYRING)
> 
> And, when more security modules are added update this CONFIG as appropriate.
> 
> Does that sound okay?

Yes, I think so.

Tyler

> 
>  -lakshmi

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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-07-30  3:47 ` [PATCH v5 3/4] LSM: Define SELinux function to measure " Lakshmi Ramasubramanian
@ 2020-08-03 15:11   ` Stephen Smalley
  2020-08-03 16:14     ` Lakshmi Ramasubramanian
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2020-08-03 15:11 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian, zohar, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

On 7/29/20 11:47 PM, Lakshmi Ramasubramanian wrote:

> SELinux configuration and policy are some of the critical data for this
> security module that needs to be measured. This measurement can be used
> by an attestation service, for instance, to verify if the configuration
> and policies have been setup correctly and that they haven't been tampered
> with at runtime.
>
> Measure SELinux configuration, policy capabilities settings, and the
> loaded policy by calling the IMA hooks ima_measure_lsm_state() and
> ima_measure_lsm_policy() respectively.
>
> Sample measurement of SELinux state and hash of the policy:
>
> 10 e32e...5ac3 ima-buf sha256:86e8...4594 selinux-state-1595389364:287899386 696e697469616c697a65643d313b656e61626c65643d313b656e666f7263696e673d303b636865636b72657170726f743d313b6e6574776f726b5f706565725f636f6e74726f6c733d313b6f70656e5f7065726d733d313b657874656e6465645f736f636b65745f636c6173733d313b616c776179735f636865636b5f6e6574776f726b3d303b6367726f75705f7365636c6162656c3d313b6e6e705f6e6f737569645f7472616e736974696f6e3d313b67656e66735f7365636c6162656c5f73796d6c696e6b733d303
> 10 f4a7...9408 ima-ng sha256:8d1d...1834 selinux-policy-hash-1595389353:863934271
>
> 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 -m 1 "selinux-state" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | 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
>
> 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 -m 1 "selinux-policy-hash" /sys/kernel/security/integrity/ima/ascii_runtime_measurements | cut -d' ' -f 4
>
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> Reported-by: kernel test robot <lkp@intel.com> # error: implicit declaration of function 'vfree'
> Reported-by: kernel test robot <lkp@intel.com> # error: implicit declaration of function 'crypto_alloc_shash'
> Reported-by: kernel test robot <lkp@intel.com> # sparse: symbol 'security_read_selinux_policy' was not declared. Should it be static?

Possibly I'm missing something but with these patches applied on top of 
next-integrity, and the following lines added to /etc/ima/ima-policy:

measure func=LSM_STATE template=ima-buf
measure func=LSM_POLICY

I still don't get the selinux-state or selinux-policy-hash entries in 
the ascii_runtime_measurements file.  No errors during loading of the 
ima policy as far as I can see.



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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-03 15:11   ` Stephen Smalley
@ 2020-08-03 16:14     ` Lakshmi Ramasubramanian
  2020-08-03 20:00       ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-08-03 16:14 UTC (permalink / raw)
  To: Stephen Smalley, zohar, casey
  Cc: tyhicks, sashal, jmorris, linux-integrity, selinux,
	linux-security-module, linux-kernel

On 8/3/20 8:11 AM, Stephen Smalley wrote:
> 
> Possibly I'm missing something but with these patches applied on top of 
> next-integrity, and the following lines added to /etc/ima/ima-policy:
> 
> measure func=LSM_STATE template=ima-buf
> measure func=LSM_POLICY
> 
> I still don't get the selinux-state or selinux-policy-hash entries in 
> the ascii_runtime_measurements file.  No errors during loading of the 
> ima policy as far as I can see.
> 

Could you please check if the following config is set?
CONFIG_IMA_QUEUE_EARLY_BOOT_DATA=y

Try changing /sys/fs/selinux/checkreqprot and check 
ascii_runtime_measurements file again?

Also, could you please check if
/sys/kernel/security/integrity/ima/policy contains LSM_STATE and 
LSM_POLICY entries?

  -lakshmi



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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-03 16:14     ` Lakshmi Ramasubramanian
@ 2020-08-03 20:00       ` Stephen Smalley
  2020-08-03 20:29         ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2020-08-03 20:00 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On Mon, Aug 3, 2020 at 12:14 PM Lakshmi Ramasubramanian
<nramas@linux.microsoft.com> wrote:
>
> On 8/3/20 8:11 AM, Stephen Smalley wrote:
> >
> > Possibly I'm missing something but with these patches applied on top of
> > next-integrity, and the following lines added to /etc/ima/ima-policy:
> >
> > measure func=LSM_STATE template=ima-buf
> > measure func=LSM_POLICY
> >
> > I still don't get the selinux-state or selinux-policy-hash entries in
> > the ascii_runtime_measurements file.  No errors during loading of the
> > ima policy as far as I can see.
> >
>
> Could you please check if the following config is set?
> CONFIG_IMA_QUEUE_EARLY_BOOT_DATA=y

Yes, I have that set.

> Try changing /sys/fs/selinux/checkreqprot and check
> ascii_runtime_measurements file again?

No change.  Likewise for changing enforce or running load_policy again.

> Also, could you please check if
> /sys/kernel/security/integrity/ima/policy contains LSM_STATE and
> LSM_POLICY entries?

Yes, it does.  However, I noticed that if I reduce the policy to only
contain those entries and no others and reboot, then I get
measurements.  Whereas if I append them to an existing policy like the
one below, they seem to be ignored:
dont_measure fsmagic=0x9fa0
dont_measure fsmagic=0x62656572
dont_measure fsmagic=0x64626720
dont_measure fsmagic=0x1021994
dont_measure fsmagic=0x858458f6
dont_measure fsmagic=0x73636673
measure func=BPRM_CHECK
measure func=MMAP_CHECK mask=MAY_EXEC
measure func=MODULE_CHECK uid=0
measure func=LSM_STATE template=ima-buf
measure func=LSM_POLICY

Also, I noticed the following in my dmesg output:
[   68.870715] ------------[ cut here ]------------
[   68.870715] WARNING: CPU: 2 PID: 1 at mm/page_alloc.c:4826
__alloc_pages_nodemask+0x627/0x700
[   68.870715] Modules linked in: 8139too crct10dif_pclmul
crc32_pclmul crc32c_intel ghash_clmulni_intel qxl serio_raw
drm_ttm_helper ttm drm_kms_helper virtio_console cec drm 8139cp
ata_generic mii pata_acpi floppy qemu_fw_cfg fuse
[   68.870715] CPU: 2 PID: 1 Comm: systemd Not tainted 5.8.0-rc2+ #44
[   68.870715] RIP: 0010:__alloc_pages_nodemask+0x627/0x700
[   68.870715] Code: ff ff 75 6c 48 8b 85 48 ff ff ff 4c 89 c2 44 89
e6 44 89 ff 41 c6 45 d0 00 49 89 45 b8 e8 41 e2 ff ff 49 89 c6 e9 9d
fc ff ff <0f> 0b e9 d4 fd ff ff 0f 0b e9 bc fc ff ff 0f 0b e9 f9 fd ff
ff e8
[   68.870715] RSP: 0000:ffff8881e82a7a18 EFLAGS: 00010246
[   68.870715] RAX: ffffed103d054f48 RBX: 1ffff1103d054f48 RCX: 0000000000000000
[   68.870715] RDX: 0000000000000000 RSI: 000000000000000b RDI: 0000000000000000
[   68.870715] RBP: ffff8881e82a7ae8 R08: ffffffffaa3fe2d5 R09: 0000000000000001
[   68.870715] R10: fffffbfff5a88f0f R11: 0000000000000001 R12: 00000000007eef6a
[   68.870715] R13: 0000000000040cc0 R14: 000000000000000b R15: ffffffffadde766b
[   68.870715] FS:  00007fdeb168c600(0000) GS:ffff8881e9800000(0000)
knlGS:0000000000000000
[   68.870715] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   68.870715] CR2: 00007fdeb17dd1d6 CR3: 00000001cc2d2002 CR4: 00000000003606e0
[   68.870715] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   68.870715] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   68.870715] Call Trace:
[   68.870715]  ? sched_clock_cpu+0xf5/0x110
[   68.870715]  ? __alloc_pages_slowpath.constprop.0+0x17a0/0x17a0
[   68.870715]  ? match_held_lock+0x2e/0x240
[   68.870715]  ? policy_nodemask+0x1a/0xa0
[   68.870715]  ? policy_node+0x56/0x60
[   68.870715]  kmalloc_order+0x25/0xc0
[   68.870715]  kmalloc_order_trace+0x1d/0x140
[   68.870715]  kmemdup+0x1a/0x40
[   68.870715]  ima_queue_data+0x61/0x370
[   68.870715]  ima_measure_lsm_data+0x32/0x60
[   68.870715]  selinux_measure_state+0x2b8/0x2bd
[   68.870715]  ? selinux_event_name+0xe0/0xe0
[   68.870715]  ? rcu_is_watching+0x39/0x50
[   68.870715]  security_load_policy+0x44c/0x8e0
[   68.870715]  ? mark_lock+0xa6/0xbd0
[   68.870715]  ? security_change_sid+0x90/0x90
[   68.870715]  ? mark_held_locks+0x3e/0xa0
[   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
[   68.870715]  ? asm_exc_page_fault+0x1e/0x30
[   68.870715]  ? lockdep_hardirqs_on+0xc5/0x1b0
[   68.870715]  ? asm_exc_page_fault+0x1e/0x30
[   68.870715]  ? copy_user_enhanced_fast_string+0xe/0x30
[   68.870715]  sel_write_load+0x157/0x260
[   68.870715]  vfs_write+0x135/0x290
[   68.870715]  ksys_write+0xb1/0x140
[   68.870715]  ? __ia32_sys_read+0x50/0x50
[   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
[   68.870715]  ? do_syscall_64+0x12/0xb0
[   68.870715]  do_syscall_64+0x52/0xb0
[   68.870715]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   68.870715] RIP: 0033:0x7fdeb2539497
[   68.870715] Code: Bad RIP value.
[   68.870715] RSP: 002b:00007fff6352b308 EFLAGS: 00000246 ORIG_RAX:
0000000000000001
[   68.870715] RAX: ffffffffffffffda RBX: 0000000000000020 RCX: 00007fdeb2539497
[   68.870715] RDX: 00000000007eef6a RSI: 00007fdeb0de1000 RDI: 0000000000000004
[   68.870715] RBP: 0000000000000004 R08: 00007fdeb25d0040 R09: 00007fff6352b1a0
[   68.870715] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fdeb0de1000
[   68.870715] R13: 00000000007eef6a R14: 000000000000000f R15: 0000000000000003
[   68.870715] irq event stamp: 23486085
[   68.870715] hardirqs last  enabled at (23486085):
[<ffffffffaa419406>] _raw_spin_unlock_irqrestore+0x46/0x60
[   68.870715] hardirqs last disabled at (23486084):
[<ffffffffaa419443>] _raw_spin_lock_irqsave+0x23/0x90
[   68.870715] softirqs last  enabled at (23486074):
[<ffffffffaa8004f3>] __do_softirq+0x4f3/0x662
[   68.870715] softirqs last disabled at (23486067):
[<ffffffffaa601072>] asm_call_on_stack+0x12/0x20
[   68.870715] ---[ end trace fb02740ff6f4d0cd ]---

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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-03 20:00       ` Stephen Smalley
@ 2020-08-03 20:29         ` Stephen Smalley
  2020-08-03 20:37           ` Lakshmi Ramasubramanian
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2020-08-03 20:29 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On 8/3/20 4:00 PM, Stephen Smalley wrote:

> On Mon, Aug 3, 2020 at 12:14 PM Lakshmi Ramasubramanian
> <nramas@linux.microsoft.com> wrote:
>> On 8/3/20 8:11 AM, Stephen Smalley wrote:
>>> Possibly I'm missing something but with these patches applied on top of
>>> next-integrity, and the following lines added to /etc/ima/ima-policy:
>>>
>>> measure func=LSM_STATE template=ima-buf
>>> measure func=LSM_POLICY
>>>
>>> I still don't get the selinux-state or selinux-policy-hash entries in
>>> the ascii_runtime_measurements file.  No errors during loading of the
>>> ima policy as far as I can see.
>>>
>> Could you please check if the following config is set?
>> CONFIG_IMA_QUEUE_EARLY_BOOT_DATA=y
> Yes, I have that set.
>
>> Try changing /sys/fs/selinux/checkreqprot and check
>> ascii_runtime_measurements file again?
> No change.  Likewise for changing enforce or running load_policy again.
>
>> Also, could you please check if
>> /sys/kernel/security/integrity/ima/policy contains LSM_STATE and
>> LSM_POLICY entries?
> Yes, it does.  However, I noticed that if I reduce the policy to only
> contain those entries and no others and reboot, then I get
> measurements.  Whereas if I append them to an existing policy like the
> one below, they seem to be ignored:
> dont_measure fsmagic=0x9fa0
> dont_measure fsmagic=0x62656572
> dont_measure fsmagic=0x64626720
> dont_measure fsmagic=0x1021994
> dont_measure fsmagic=0x858458f6
> dont_measure fsmagic=0x73636673
> measure func=BPRM_CHECK
> measure func=MMAP_CHECK mask=MAY_EXEC
> measure func=MODULE_CHECK uid=0
> measure func=LSM_STATE template=ima-buf
> measure func=LSM_POLICY
>
> Also, I noticed the following in my dmesg output:
> [   68.870715] ------------[ cut here ]------------
> [   68.870715] WARNING: CPU: 2 PID: 1 at mm/page_alloc.c:4826
> __alloc_pages_nodemask+0x627/0x700
> [   68.870715] Modules linked in: 8139too crct10dif_pclmul
> crc32_pclmul crc32c_intel ghash_clmulni_intel qxl serio_raw
> drm_ttm_helper ttm drm_kms_helper virtio_console cec drm 8139cp
> ata_generic mii pata_acpi floppy qemu_fw_cfg fuse
> [   68.870715] CPU: 2 PID: 1 Comm: systemd Not tainted 5.8.0-rc2+ #44
> [   68.870715] RIP: 0010:__alloc_pages_nodemask+0x627/0x700
> [   68.870715] Code: ff ff 75 6c 48 8b 85 48 ff ff ff 4c 89 c2 44 89
> e6 44 89 ff 41 c6 45 d0 00 49 89 45 b8 e8 41 e2 ff ff 49 89 c6 e9 9d
> fc ff ff <0f> 0b e9 d4 fd ff ff 0f 0b e9 bc fc ff ff 0f 0b e9 f9 fd ff
> ff e8
> [   68.870715] RSP: 0000:ffff8881e82a7a18 EFLAGS: 00010246
> [   68.870715] RAX: ffffed103d054f48 RBX: 1ffff1103d054f48 RCX: 0000000000000000
> [   68.870715] RDX: 0000000000000000 RSI: 000000000000000b RDI: 0000000000000000
> [   68.870715] RBP: ffff8881e82a7ae8 R08: ffffffffaa3fe2d5 R09: 0000000000000001
> [   68.870715] R10: fffffbfff5a88f0f R11: 0000000000000001 R12: 00000000007eef6a
> [   68.870715] R13: 0000000000040cc0 R14: 000000000000000b R15: ffffffffadde766b
> [   68.870715] FS:  00007fdeb168c600(0000) GS:ffff8881e9800000(0000)
> knlGS:0000000000000000
> [   68.870715] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   68.870715] CR2: 00007fdeb17dd1d6 CR3: 00000001cc2d2002 CR4: 00000000003606e0
> [   68.870715] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [   68.870715] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> [   68.870715] Call Trace:
> [   68.870715]  ? sched_clock_cpu+0xf5/0x110
> [   68.870715]  ? __alloc_pages_slowpath.constprop.0+0x17a0/0x17a0
> [   68.870715]  ? match_held_lock+0x2e/0x240
> [   68.870715]  ? policy_nodemask+0x1a/0xa0
> [   68.870715]  ? policy_node+0x56/0x60
> [   68.870715]  kmalloc_order+0x25/0xc0
> [   68.870715]  kmalloc_order_trace+0x1d/0x140
> [   68.870715]  kmemdup+0x1a/0x40
> [   68.870715]  ima_queue_data+0x61/0x370
> [   68.870715]  ima_measure_lsm_data+0x32/0x60
> [   68.870715]  selinux_measure_state+0x2b8/0x2bd
> [   68.870715]  ? selinux_event_name+0xe0/0xe0
> [   68.870715]  ? rcu_is_watching+0x39/0x50
> [   68.870715]  security_load_policy+0x44c/0x8e0
> [   68.870715]  ? mark_lock+0xa6/0xbd0
> [   68.870715]  ? security_change_sid+0x90/0x90
> [   68.870715]  ? mark_held_locks+0x3e/0xa0
> [   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
> [   68.870715]  ? asm_exc_page_fault+0x1e/0x30
> [   68.870715]  ? lockdep_hardirqs_on+0xc5/0x1b0
> [   68.870715]  ? asm_exc_page_fault+0x1e/0x30
> [   68.870715]  ? copy_user_enhanced_fast_string+0xe/0x30
> [   68.870715]  sel_write_load+0x157/0x260
> [   68.870715]  vfs_write+0x135/0x290
> [   68.870715]  ksys_write+0xb1/0x140
> [   68.870715]  ? __ia32_sys_read+0x50/0x50
> [   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
> [   68.870715]  ? do_syscall_64+0x12/0xb0
> [   68.870715]  do_syscall_64+0x52/0xb0
> [   68.870715]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
> [   68.870715] RIP: 0033:0x7fdeb2539497
> [   68.870715] Code: Bad RIP value.
> [   68.870715] RSP: 002b:00007fff6352b308 EFLAGS: 00000246 ORIG_RAX:
> 0000000000000001
> [   68.870715] RAX: ffffffffffffffda RBX: 0000000000000020 RCX: 00007fdeb2539497
> [   68.870715] RDX: 00000000007eef6a RSI: 00007fdeb0de1000 RDI: 0000000000000004
> [   68.870715] RBP: 0000000000000004 R08: 00007fdeb25d0040 R09: 00007fff6352b1a0
> [   68.870715] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fdeb0de1000
> [   68.870715] R13: 00000000007eef6a R14: 000000000000000f R15: 0000000000000003
> [   68.870715] irq event stamp: 23486085
> [   68.870715] hardirqs last  enabled at (23486085):
> [<ffffffffaa419406>] _raw_spin_unlock_irqrestore+0x46/0x60
> [   68.870715] hardirqs last disabled at (23486084):
> [<ffffffffaa419443>] _raw_spin_lock_irqsave+0x23/0x90
> [   68.870715] softirqs last  enabled at (23486074):
> [<ffffffffaa8004f3>] __do_softirq+0x4f3/0x662
> [   68.870715] softirqs last disabled at (23486067):
> [<ffffffffaa601072>] asm_call_on_stack+0x12/0x20
> [   68.870715] ---[ end trace fb02740ff6f4d0cd ]---

I think one issue here is that systemd loads SELinux policy first, then 
IMA policy, so it doesn't know whether it needs to measure SELinux 
policy on first policy load, and another issue is that the policy is too 
large to just queue the policy data itself this way (or you need to use 
an allocator that can handle larger sizes).



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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-03 20:29         ` Stephen Smalley
@ 2020-08-03 20:37           ` Lakshmi Ramasubramanian
  2020-08-03 21:07             ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-08-03 20:37 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On 8/3/20 1:29 PM, Stephen Smalley wrote:
> On 8/3/20 4:00 PM, Stephen Smalley wrote:
> 
>> On Mon, Aug 3, 2020 at 12:14 PM Lakshmi Ramasubramanian
>> <nramas@linux.microsoft.com> wrote:
>>> On 8/3/20 8:11 AM, Stephen Smalley wrote:
>>>> Possibly I'm missing something but with these patches applied on top of
>>>> next-integrity, and the following lines added to /etc/ima/ima-policy:
>>>>
>>>> measure func=LSM_STATE template=ima-buf
>>>> measure func=LSM_POLICY
>>>>
>>>> I still don't get the selinux-state or selinux-policy-hash entries in
>>>> the ascii_runtime_measurements file.  No errors during loading of the
>>>> ima policy as far as I can see.
>>>>
>>> Could you please check if the following config is set?
>>> CONFIG_IMA_QUEUE_EARLY_BOOT_DATA=y
>> Yes, I have that set.
>>
>>> Try changing /sys/fs/selinux/checkreqprot and check
>>> ascii_runtime_measurements file again?
>> No change.  Likewise for changing enforce or running load_policy again.
>>
>>> Also, could you please check if
>>> /sys/kernel/security/integrity/ima/policy contains LSM_STATE and
>>> LSM_POLICY entries?
>> Yes, it does.  However, I noticed that if I reduce the policy to only
>> contain those entries and no others and reboot, then I get
>> measurements.  Whereas if I append them to an existing policy like the
>> one below, they seem to be ignored:
>> dont_measure fsmagic=0x9fa0
>> dont_measure fsmagic=0x62656572
>> dont_measure fsmagic=0x64626720
>> dont_measure fsmagic=0x1021994
>> dont_measure fsmagic=0x858458f6
>> dont_measure fsmagic=0x73636673
>> measure func=BPRM_CHECK
>> measure func=MMAP_CHECK mask=MAY_EXEC
>> measure func=MODULE_CHECK uid=0
>> measure func=LSM_STATE template=ima-buf
>> measure func=LSM_POLICY
>>
>> Also, I noticed the following in my dmesg output:
>> [   68.870715] ------------[ cut here ]------------
>> [   68.870715] WARNING: CPU: 2 PID: 1 at mm/page_alloc.c:4826
>> __alloc_pages_nodemask+0x627/0x700
>> [   68.870715] Modules linked in: 8139too crct10dif_pclmul
>> crc32_pclmul crc32c_intel ghash_clmulni_intel qxl serio_raw
>> drm_ttm_helper ttm drm_kms_helper virtio_console cec drm 8139cp
>> ata_generic mii pata_acpi floppy qemu_fw_cfg fuse
>> [   68.870715] CPU: 2 PID: 1 Comm: systemd Not tainted 5.8.0-rc2+ #44
>> [   68.870715] RIP: 0010:__alloc_pages_nodemask+0x627/0x700
>> [   68.870715] Code: ff ff 75 6c 48 8b 85 48 ff ff ff 4c 89 c2 44 89
>> e6 44 89 ff 41 c6 45 d0 00 49 89 45 b8 e8 41 e2 ff ff 49 89 c6 e9 9d
>> fc ff ff <0f> 0b e9 d4 fd ff ff 0f 0b e9 bc fc ff ff 0f 0b e9 f9 fd ff
>> ff e8
>> [   68.870715] RSP: 0000:ffff8881e82a7a18 EFLAGS: 00010246
>> [   68.870715] RAX: ffffed103d054f48 RBX: 1ffff1103d054f48 RCX: 
>> 0000000000000000
>> [   68.870715] RDX: 0000000000000000 RSI: 000000000000000b RDI: 
>> 0000000000000000
>> [   68.870715] RBP: ffff8881e82a7ae8 R08: ffffffffaa3fe2d5 R09: 
>> 0000000000000001
>> [   68.870715] R10: fffffbfff5a88f0f R11: 0000000000000001 R12: 
>> 00000000007eef6a
>> [   68.870715] R13: 0000000000040cc0 R14: 000000000000000b R15: 
>> ffffffffadde766b
>> [   68.870715] FS:  00007fdeb168c600(0000) GS:ffff8881e9800000(0000)
>> knlGS:0000000000000000
>> [   68.870715] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> [   68.870715] CR2: 00007fdeb17dd1d6 CR3: 00000001cc2d2002 CR4: 
>> 00000000003606e0
>> [   68.870715] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 
>> 0000000000000000
>> [   68.870715] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 
>> 0000000000000400
>> [   68.870715] Call Trace:
>> [   68.870715]  ? sched_clock_cpu+0xf5/0x110
>> [   68.870715]  ? __alloc_pages_slowpath.constprop.0+0x17a0/0x17a0
>> [   68.870715]  ? match_held_lock+0x2e/0x240
>> [   68.870715]  ? policy_nodemask+0x1a/0xa0
>> [   68.870715]  ? policy_node+0x56/0x60
>> [   68.870715]  kmalloc_order+0x25/0xc0
>> [   68.870715]  kmalloc_order_trace+0x1d/0x140
>> [   68.870715]  kmemdup+0x1a/0x40
>> [   68.870715]  ima_queue_data+0x61/0x370
>> [   68.870715]  ima_measure_lsm_data+0x32/0x60
>> [   68.870715]  selinux_measure_state+0x2b8/0x2bd
>> [   68.870715]  ? selinux_event_name+0xe0/0xe0
>> [   68.870715]  ? rcu_is_watching+0x39/0x50
>> [   68.870715]  security_load_policy+0x44c/0x8e0
>> [   68.870715]  ? mark_lock+0xa6/0xbd0
>> [   68.870715]  ? security_change_sid+0x90/0x90
>> [   68.870715]  ? mark_held_locks+0x3e/0xa0
>> [   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
>> [   68.870715]  ? asm_exc_page_fault+0x1e/0x30
>> [   68.870715]  ? lockdep_hardirqs_on+0xc5/0x1b0
>> [   68.870715]  ? asm_exc_page_fault+0x1e/0x30
>> [   68.870715]  ? copy_user_enhanced_fast_string+0xe/0x30
>> [   68.870715]  sel_write_load+0x157/0x260
>> [   68.870715]  vfs_write+0x135/0x290
>> [   68.870715]  ksys_write+0xb1/0x140
>> [   68.870715]  ? __ia32_sys_read+0x50/0x50
>> [   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
>> [   68.870715]  ? do_syscall_64+0x12/0xb0
>> [   68.870715]  do_syscall_64+0x52/0xb0
>> [   68.870715]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
>> [   68.870715] RIP: 0033:0x7fdeb2539497
>> [   68.870715] Code: Bad RIP value.
>> [   68.870715] RSP: 002b:00007fff6352b308 EFLAGS: 00000246 ORIG_RAX:
>> 0000000000000001
>> [   68.870715] RAX: ffffffffffffffda RBX: 0000000000000020 RCX: 
>> 00007fdeb2539497
>> [   68.870715] RDX: 00000000007eef6a RSI: 00007fdeb0de1000 RDI: 
>> 0000000000000004
>> [   68.870715] RBP: 0000000000000004 R08: 00007fdeb25d0040 R09: 
>> 00007fff6352b1a0
>> [   68.870715] R10: 0000000000000000 R11: 0000000000000246 R12: 
>> 00007fdeb0de1000
>> [   68.870715] R13: 00000000007eef6a R14: 000000000000000f R15: 
>> 0000000000000003
>> [   68.870715] irq event stamp: 23486085
>> [   68.870715] hardirqs last  enabled at (23486085):
>> [<ffffffffaa419406>] _raw_spin_unlock_irqrestore+0x46/0x60
>> [   68.870715] hardirqs last disabled at (23486084):
>> [<ffffffffaa419443>] _raw_spin_lock_irqsave+0x23/0x90
>> [   68.870715] softirqs last  enabled at (23486074):
>> [<ffffffffaa8004f3>] __do_softirq+0x4f3/0x662
>> [   68.870715] softirqs last disabled at (23486067):
>> [<ffffffffaa601072>] asm_call_on_stack+0x12/0x20
>> [   68.870715] ---[ end trace fb02740ff6f4d0cd ]---
> 
> I think one issue here is that systemd loads SELinux policy first, then 
> IMA policy, so it doesn't know whether it needs to measure SELinux 
> policy on first policy load, and another issue is that the policy is too 
> large to just queue the policy data itself this way (or you need to use 
> an allocator that can handle larger sizes).
> 

The problem seems to be that a lock is held when the IMA hook to measure 
the LSM state is called. So memory allocation is not allowed, but the 
hook is doing an allocation. I'll address this - thanks for catching it.

I have the following CONFIGs enabled, but I still don't see the above 
issue on my machine.

Could you please let me know what CONFIG(s) to enable?

#
# Lock Debugging (spinlocks, mutexes, etc...)
#
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
CONFIG_DEBUG_RWSEMS=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_LOCKDEP=y
CONFIG_DEBUG_ATOMIC_SLEEP=y

I'll also try with the policy you have, check why the LSM policy is 
ignored when there are other policy entries.

thanks,
  -lakshmi


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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-03 20:37           ` Lakshmi Ramasubramanian
@ 2020-08-03 21:07             ` Stephen Smalley
  2020-08-03 22:08               ` Lakshmi Ramasubramanian
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2020-08-03 21:07 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On 8/3/20 4:37 PM, Lakshmi Ramasubramanian wrote:

> On 8/3/20 1:29 PM, Stephen Smalley wrote:
>> On 8/3/20 4:00 PM, Stephen Smalley wrote:
>>
>>> On Mon, Aug 3, 2020 at 12:14 PM Lakshmi Ramasubramanian
>>> <nramas@linux.microsoft.com> wrote:
>>>> On 8/3/20 8:11 AM, Stephen Smalley wrote:
>>>>> Possibly I'm missing something but with these patches applied on 
>>>>> top of
>>>>> next-integrity, and the following lines added to /etc/ima/ima-policy:
>>>>>
>>>>> measure func=LSM_STATE template=ima-buf
>>>>> measure func=LSM_POLICY
>>>>>
>>>>> I still don't get the selinux-state or selinux-policy-hash entries in
>>>>> the ascii_runtime_measurements file.  No errors during loading of the
>>>>> ima policy as far as I can see.
>>>>>
>>>> Could you please check if the following config is set?
>>>> CONFIG_IMA_QUEUE_EARLY_BOOT_DATA=y
>>> Yes, I have that set.
>>>
>>>> Try changing /sys/fs/selinux/checkreqprot and check
>>>> ascii_runtime_measurements file again?
>>> No change.  Likewise for changing enforce or running load_policy again.
>>>
>>>> Also, could you please check if
>>>> /sys/kernel/security/integrity/ima/policy contains LSM_STATE and
>>>> LSM_POLICY entries?
>>> Yes, it does.  However, I noticed that if I reduce the policy to only
>>> contain those entries and no others and reboot, then I get
>>> measurements.  Whereas if I append them to an existing policy like the
>>> one below, they seem to be ignored:
>>> dont_measure fsmagic=0x9fa0
>>> dont_measure fsmagic=0x62656572
>>> dont_measure fsmagic=0x64626720
>>> dont_measure fsmagic=0x1021994
>>> dont_measure fsmagic=0x858458f6
>>> dont_measure fsmagic=0x73636673
>>> measure func=BPRM_CHECK
>>> measure func=MMAP_CHECK mask=MAY_EXEC
>>> measure func=MODULE_CHECK uid=0
>>> measure func=LSM_STATE template=ima-buf
>>> measure func=LSM_POLICY
>>>
>>> Also, I noticed the following in my dmesg output:
>>> [   68.870715] ------------[ cut here ]------------
>>> [   68.870715] WARNING: CPU: 2 PID: 1 at mm/page_alloc.c:4826
>>> __alloc_pages_nodemask+0x627/0x700
>>> [   68.870715] Modules linked in: 8139too crct10dif_pclmul
>>> crc32_pclmul crc32c_intel ghash_clmulni_intel qxl serio_raw
>>> drm_ttm_helper ttm drm_kms_helper virtio_console cec drm 8139cp
>>> ata_generic mii pata_acpi floppy qemu_fw_cfg fuse
>>> [   68.870715] CPU: 2 PID: 1 Comm: systemd Not tainted 5.8.0-rc2+ #44
>>> [   68.870715] RIP: 0010:__alloc_pages_nodemask+0x627/0x700
>>> [   68.870715] Code: ff ff 75 6c 48 8b 85 48 ff ff ff 4c 89 c2 44 89
>>> e6 44 89 ff 41 c6 45 d0 00 49 89 45 b8 e8 41 e2 ff ff 49 89 c6 e9 9d
>>> fc ff ff <0f> 0b e9 d4 fd ff ff 0f 0b e9 bc fc ff ff 0f 0b e9 f9 fd ff
>>> ff e8
>>> [   68.870715] RSP: 0000:ffff8881e82a7a18 EFLAGS: 00010246
>>> [   68.870715] RAX: ffffed103d054f48 RBX: 1ffff1103d054f48 RCX: 
>>> 0000000000000000
>>> [   68.870715] RDX: 0000000000000000 RSI: 000000000000000b RDI: 
>>> 0000000000000000
>>> [   68.870715] RBP: ffff8881e82a7ae8 R08: ffffffffaa3fe2d5 R09: 
>>> 0000000000000001
>>> [   68.870715] R10: fffffbfff5a88f0f R11: 0000000000000001 R12: 
>>> 00000000007eef6a
>>> [   68.870715] R13: 0000000000040cc0 R14: 000000000000000b R15: 
>>> ffffffffadde766b
>>> [   68.870715] FS:  00007fdeb168c600(0000) GS:ffff8881e9800000(0000)
>>> knlGS:0000000000000000
>>> [   68.870715] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>>> [   68.870715] CR2: 00007fdeb17dd1d6 CR3: 00000001cc2d2002 CR4: 
>>> 00000000003606e0
>>> [   68.870715] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 
>>> 0000000000000000
>>> [   68.870715] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 
>>> 0000000000000400
>>> [   68.870715] Call Trace:
>>> [   68.870715]  ? sched_clock_cpu+0xf5/0x110
>>> [   68.870715]  ? __alloc_pages_slowpath.constprop.0+0x17a0/0x17a0
>>> [   68.870715]  ? match_held_lock+0x2e/0x240
>>> [   68.870715]  ? policy_nodemask+0x1a/0xa0
>>> [   68.870715]  ? policy_node+0x56/0x60
>>> [   68.870715]  kmalloc_order+0x25/0xc0
>>> [   68.870715]  kmalloc_order_trace+0x1d/0x140
>>> [   68.870715]  kmemdup+0x1a/0x40
>>> [   68.870715]  ima_queue_data+0x61/0x370
>>> [   68.870715]  ima_measure_lsm_data+0x32/0x60
>>> [   68.870715]  selinux_measure_state+0x2b8/0x2bd
>>> [   68.870715]  ? selinux_event_name+0xe0/0xe0
>>> [   68.870715]  ? rcu_is_watching+0x39/0x50
>>> [   68.870715]  security_load_policy+0x44c/0x8e0
>>> [   68.870715]  ? mark_lock+0xa6/0xbd0
>>> [   68.870715]  ? security_change_sid+0x90/0x90
>>> [   68.870715]  ? mark_held_locks+0x3e/0xa0
>>> [   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
>>> [   68.870715]  ? asm_exc_page_fault+0x1e/0x30
>>> [   68.870715]  ? lockdep_hardirqs_on+0xc5/0x1b0
>>> [   68.870715]  ? asm_exc_page_fault+0x1e/0x30
>>> [   68.870715]  ? copy_user_enhanced_fast_string+0xe/0x30
>>> [   68.870715]  sel_write_load+0x157/0x260
>>> [   68.870715]  vfs_write+0x135/0x290
>>> [   68.870715]  ksys_write+0xb1/0x140
>>> [   68.870715]  ? __ia32_sys_read+0x50/0x50
>>> [   68.870715]  ? lockdep_hardirqs_on_prepare+0x100/0x260
>>> [   68.870715]  ? do_syscall_64+0x12/0xb0
>>> [   68.870715]  do_syscall_64+0x52/0xb0
>>> [   68.870715]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
>>> [   68.870715] RIP: 0033:0x7fdeb2539497
>>> [   68.870715] Code: Bad RIP value.
>>> [   68.870715] RSP: 002b:00007fff6352b308 EFLAGS: 00000246 ORIG_RAX:
>>> 0000000000000001
>>> [   68.870715] RAX: ffffffffffffffda RBX: 0000000000000020 RCX: 
>>> 00007fdeb2539497
>>> [   68.870715] RDX: 00000000007eef6a RSI: 00007fdeb0de1000 RDI: 
>>> 0000000000000004
>>> [   68.870715] RBP: 0000000000000004 R08: 00007fdeb25d0040 R09: 
>>> 00007fff6352b1a0
>>> [   68.870715] R10: 0000000000000000 R11: 0000000000000246 R12: 
>>> 00007fdeb0de1000
>>> [   68.870715] R13: 00000000007eef6a R14: 000000000000000f R15: 
>>> 0000000000000003
>>> [   68.870715] irq event stamp: 23486085
>>> [   68.870715] hardirqs last  enabled at (23486085):
>>> [<ffffffffaa419406>] _raw_spin_unlock_irqrestore+0x46/0x60
>>> [   68.870715] hardirqs last disabled at (23486084):
>>> [<ffffffffaa419443>] _raw_spin_lock_irqsave+0x23/0x90
>>> [   68.870715] softirqs last  enabled at (23486074):
>>> [<ffffffffaa8004f3>] __do_softirq+0x4f3/0x662
>>> [   68.870715] softirqs last disabled at (23486067):
>>> [<ffffffffaa601072>] asm_call_on_stack+0x12/0x20
>>> [   68.870715] ---[ end trace fb02740ff6f4d0cd ]---
>>
>> I think one issue here is that systemd loads SELinux policy first, 
>> then IMA policy, so it doesn't know whether it needs to measure 
>> SELinux policy on first policy load, and another issue is that the 
>> policy is too large to just queue the policy data itself this way (or 
>> you need to use an allocator that can handle larger sizes).
>>
>
> The problem seems to be that a lock is held when the IMA hook to 
> measure the LSM state is called. So memory allocation is not allowed, 
> but the hook is doing an allocation. I'll address this - thanks for 
> catching it.
>
> I have the following CONFIGs enabled, but I still don't see the above 
> issue on my machine.
>
The warning has to do with the memory allocation order being above the 
max order supported for kmalloc.  I think the problem is that 
ima_alloc_data_entry() is using kmemdup() to duplicate a payload of 
arbitrary size.  Policies on e.g. Fedora can be quite large, so you 
can't assume they can be allocated with kmalloc and friends.



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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-03 21:07             ` Stephen Smalley
@ 2020-08-03 22:08               ` Lakshmi Ramasubramanian
  2020-08-04 15:20                 ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-08-03 22:08 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On 8/3/20 2:07 PM, Stephen Smalley wrote:

>>>> [   68.870715] irq event stamp: 23486085
>>>> [   68.870715] hardirqs last  enabled at (23486085):
>>>> [<ffffffffaa419406>] _raw_spin_unlock_irqrestore+0x46/0x60
>>>> [   68.870715] hardirqs last disabled at (23486084):
>>>> [<ffffffffaa419443>] _raw_spin_lock_irqsave+0x23/0x90
>>>> [   68.870715] softirqs last  enabled at (23486074):
>>>> [<ffffffffaa8004f3>] __do_softirq+0x4f3/0x662
>>>> [   68.870715] softirqs last disabled at (23486067):
>>>> [<ffffffffaa601072>] asm_call_on_stack+0x12/0x20
>>>> [   68.870715] ---[ end trace fb02740ff6f4d0cd ]---
>>>
>>> I think one issue here is that systemd loads SELinux policy first, 
>>> then IMA policy, so it doesn't know whether it needs to measure 
>>> SELinux policy on first policy load, and another issue is that the 
>>> policy is too large to just queue the policy data itself this way (or 
>>> you need to use an allocator that can handle larger sizes).
>>>
>>
>> The problem seems to be that a lock is held when the IMA hook to 
>> measure the LSM state is called. So memory allocation is not allowed, 
>> but the hook is doing an allocation. I'll address this - thanks for 
>> catching it.
>>
>> I have the following CONFIGs enabled, but I still don't see the above 
>> issue on my machine.
>>
> The warning has to do with the memory allocation order being above the 
> max order supported for kmalloc.  I think the problem is that 
> ima_alloc_data_entry() is using kmemdup() to duplicate a payload of 
> arbitrary size.  Policies on e.g. Fedora can be quite large, so you 
> can't assume they can be allocated with kmalloc and friends.
> 

Thanks for clarifying. Yes ima_alloc_entry() does use kmemdup to save 
the given buffer (to be measured) until IMA loads custom policy.

On my machine the SELinux policy size is about 2MB.

Perhaps vmalloc would be better than using kmalloc? If there are better 
options for such large buffer allocation, please let me know.

  -lakshmi

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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-03 22:08               ` Lakshmi Ramasubramanian
@ 2020-08-04 15:20                 ` Stephen Smalley
  2020-08-04 15:29                   ` Stephen Smalley
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2020-08-04 15:20 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On 8/3/20 6:08 PM, Lakshmi Ramasubramanian wrote:

> On 8/3/20 2:07 PM, Stephen Smalley wrote:
>
>>>>> [   68.870715] irq event stamp: 23486085
>>>>> [   68.870715] hardirqs last  enabled at (23486085):
>>>>> [<ffffffffaa419406>] _raw_spin_unlock_irqrestore+0x46/0x60
>>>>> [   68.870715] hardirqs last disabled at (23486084):
>>>>> [<ffffffffaa419443>] _raw_spin_lock_irqsave+0x23/0x90
>>>>> [   68.870715] softirqs last  enabled at (23486074):
>>>>> [<ffffffffaa8004f3>] __do_softirq+0x4f3/0x662
>>>>> [   68.870715] softirqs last disabled at (23486067):
>>>>> [<ffffffffaa601072>] asm_call_on_stack+0x12/0x20
>>>>> [   68.870715] ---[ end trace fb02740ff6f4d0cd ]---
>>>>
>>>> I think one issue here is that systemd loads SELinux policy first, 
>>>> then IMA policy, so it doesn't know whether it needs to measure 
>>>> SELinux policy on first policy load, and another issue is that the 
>>>> policy is too large to just queue the policy data itself this way 
>>>> (or you need to use an allocator that can handle larger sizes).
>>>>
>>>
>>> The problem seems to be that a lock is held when the IMA hook to 
>>> measure the LSM state is called. So memory allocation is not 
>>> allowed, but the hook is doing an allocation. I'll address this - 
>>> thanks for catching it.
>>>
>>> I have the following CONFIGs enabled, but I still don't see the 
>>> above issue on my machine.
>>>
>> The warning has to do with the memory allocation order being above 
>> the max order supported for kmalloc.  I think the problem is that 
>> ima_alloc_data_entry() is using kmemdup() to duplicate a payload of 
>> arbitrary size.  Policies on e.g. Fedora can be quite large, so you 
>> can't assume they can be allocated with kmalloc and friends.
>>
>
> Thanks for clarifying. Yes ima_alloc_entry() does use kmemdup to save 
> the given buffer (to be measured) until IMA loads custom policy.
>
> On my machine the SELinux policy size is about 2MB.
>
> Perhaps vmalloc would be better than using kmalloc? If there are 
> better options for such large buffer allocation, please let me know.

kvmalloc() can be used to select whichever one is most appropriate.



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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-04 15:20                 ` Stephen Smalley
@ 2020-08-04 15:29                   ` Stephen Smalley
  2020-08-04 15:57                     ` Lakshmi Ramasubramanian
  0 siblings, 1 reply; 23+ messages in thread
From: Stephen Smalley @ 2020-08-04 15:29 UTC (permalink / raw)
  To: Lakshmi Ramasubramanian
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On 8/4/20 11:20 AM, Stephen Smalley wrote:

> On 8/3/20 6:08 PM, Lakshmi Ramasubramanian wrote:
>
>> On 8/3/20 2:07 PM, Stephen Smalley wrote:
>>
>>>>>> [   68.870715] irq event stamp: 23486085
>>>>>> [   68.870715] hardirqs last  enabled at (23486085):
>>>>>> [<ffffffffaa419406>] _raw_spin_unlock_irqrestore+0x46/0x60
>>>>>> [   68.870715] hardirqs last disabled at (23486084):
>>>>>> [<ffffffffaa419443>] _raw_spin_lock_irqsave+0x23/0x90
>>>>>> [   68.870715] softirqs last  enabled at (23486074):
>>>>>> [<ffffffffaa8004f3>] __do_softirq+0x4f3/0x662
>>>>>> [   68.870715] softirqs last disabled at (23486067):
>>>>>> [<ffffffffaa601072>] asm_call_on_stack+0x12/0x20
>>>>>> [   68.870715] ---[ end trace fb02740ff6f4d0cd ]---
>>>>>
>>>>> I think one issue here is that systemd loads SELinux policy first, 
>>>>> then IMA policy, so it doesn't know whether it needs to measure 
>>>>> SELinux policy on first policy load, and another issue is that the 
>>>>> policy is too large to just queue the policy data itself this way 
>>>>> (or you need to use an allocator that can handle larger sizes).
>>>>>
>>>>
>>>> The problem seems to be that a lock is held when the IMA hook to 
>>>> measure the LSM state is called. So memory allocation is not 
>>>> allowed, but the hook is doing an allocation. I'll address this - 
>>>> thanks for catching it.
>>>>
>>>> I have the following CONFIGs enabled, but I still don't see the 
>>>> above issue on my machine.
>>>>
>>> The warning has to do with the memory allocation order being above 
>>> the max order supported for kmalloc.  I think the problem is that 
>>> ima_alloc_data_entry() is using kmemdup() to duplicate a payload of 
>>> arbitrary size.  Policies on e.g. Fedora can be quite large, so you 
>>> can't assume they can be allocated with kmalloc and friends.
>>>
>>
>> Thanks for clarifying. Yes ima_alloc_entry() does use kmemdup to save 
>> the given buffer (to be measured) until IMA loads custom policy.
>>
>> On my machine the SELinux policy size is about 2MB.
>>
>> Perhaps vmalloc would be better than using kmalloc? If there are 
>> better options for such large buffer allocation, please let me know.
>
> kvmalloc() can be used to select whichever one is most appropriate.

Other option would be for ima to compute and save the hash(es) of the 
payload and not the payload itself for later use.  I guess you won't 
know at that point which hash algorithm is desired?



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

* Re: [PATCH v5 3/4] LSM: Define SELinux function to measure state and policy
  2020-08-04 15:29                   ` Stephen Smalley
@ 2020-08-04 15:57                     ` Lakshmi Ramasubramanian
  0 siblings, 0 replies; 23+ messages in thread
From: Lakshmi Ramasubramanian @ 2020-08-04 15:57 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Mimi Zohar, Casey Schaufler, Tyler Hicks, sashal, James Morris,
	linux-integrity, SElinux list, LSM List, linux-kernel

On 8/4/20 8:29 AM, Stephen Smalley wrote:

>>> Perhaps vmalloc would be better than using kmalloc? If there are 
>>> better options for such large buffer allocation, please let me know.
>>
>> kvmalloc() can be used to select whichever one is most appropriate.
> 
> Other option would be for ima to compute and save the hash(es) of the 
> payload and not the payload itself for later use.  I guess you won't 
> know at that point which hash algorithm is desired?
> 

I think IMA hash algorithm would be known at that point, but IMA policy 
is not loaded yet (which is why I need to queue up the buffer and 
process when policy is loaded).

I tried vmalloc and tested it with upto 16MB buffer (just made up a 
SELinux policy buffer of size 16MB) - that works fine.

I will try kvmalloc().

Also, I fixed the issue with LSM data not measured when using the IMA 
policy you had. Good catch.

Will post the updated patches today.

thanks,
  -lakshmi

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

end of thread, other threads:[~2020-08-04 15:57 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-30  3:47 [PATCH v5 0/4] LSM: Measure security module data Lakshmi Ramasubramanian
2020-07-30  3:47 ` [PATCH v5 1/4] IMA: Add func to measure LSM state and policy Lakshmi Ramasubramanian
2020-07-30 15:02   ` Tyler Hicks
2020-07-30 15:15     ` Lakshmi Ramasubramanian
2020-07-30 15:17       ` Tyler Hicks
2020-07-30 16:19     ` Casey Schaufler
2020-07-30 16:33       ` Lakshmi Ramasubramanian
2020-07-30  3:47 ` [PATCH v5 2/4] IMA: Define IMA hooks " Lakshmi Ramasubramanian
2020-07-30 15:04   ` Tyler Hicks
2020-07-30  3:47 ` [PATCH v5 3/4] LSM: Define SELinux function to measure " Lakshmi Ramasubramanian
2020-08-03 15:11   ` Stephen Smalley
2020-08-03 16:14     ` Lakshmi Ramasubramanian
2020-08-03 20:00       ` Stephen Smalley
2020-08-03 20:29         ` Stephen Smalley
2020-08-03 20:37           ` Lakshmi Ramasubramanian
2020-08-03 21:07             ` Stephen Smalley
2020-08-03 22:08               ` Lakshmi Ramasubramanian
2020-08-04 15:20                 ` Stephen Smalley
2020-08-04 15:29                   ` Stephen Smalley
2020-08-04 15:57                     ` Lakshmi Ramasubramanian
2020-07-30  3:47 ` [PATCH v5 4/4] IMA: Handle early boot data measurement Lakshmi Ramasubramanian
2020-07-30 18:02   ` Lakshmi Ramasubramanian
2020-07-30 20:04     ` Tyler Hicks

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).