From: Stephen Smalley <stephen.smalley.work@gmail.com>
To: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Cc: Mimi Zohar <zohar@linux.ibm.com>,
Casey Schaufler <casey@schaufler-ca.com>,
James Morris <jmorris@namei.org>,
linux-integrity@vger.kernel.org,
SElinux list <selinux@vger.kernel.org>,
LSM List <linux-security-module@vger.kernel.org>,
linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v3 4/5] LSM: Define SELinux function to measure security state
Date: Mon, 20 Jul 2020 10:31:34 -0400 [thread overview]
Message-ID: <CAEjxPJ7xQtZToF4d2w_o8SXFKG9kPZaWTWTFqyC-7GwBWnQa0A@mail.gmail.com> (raw)
In-Reply-To: <20200717222819.26198-5-nramas@linux.microsoft.com>
On Fri, Jul 17, 2020 at 6:28 PM Lakshmi Ramasubramanian
<nramas@linux.microsoft.com> wrote:
>
> SELinux configuration and policy are some of the critical data for this
> security module that needs to be measured. To enable this measurement
> SELinux needs to implement the interface function,
> security_measure_data(), that the LSM can call.
>
> Define the security_measure_data() function in SELinux to measure SELinux
> configuration and policy. Call this function to measure SELinux data
> when there is a change in the security module's state.
>
> Sample measurement of SELinux state and hash of the policy:
>
> 10 e32e...5ac3 ima-buf sha256:86e8...4594 selinux-state 656e61626c65643d313b656e666f7263696e673d303b636865636b72657170726f743d313b6e6574706565723d313b6f70656e7065726d3d313b657874736f636b636c6173733d313b616c776179736e6574776f726b3d303b6367726f75707365636c6162656c3d313b6e6e706e6f737569647472616e736974696f6e3d313b67656e66737365636c6162656c73796d6c696e6b3d303b
> 10 f4a7...9408 ima-buf sha256:4941...68fc selinux-policy-hash 8d1d...1834
>
> To verify the measurement check the following:
>
> Execute the following command to extract the measured data
> from the IMA log for SELinux configuration (selinux-state).
>
> cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements | grep -m 1 "selinux-state" | cut -d' ' -f 6 | xxd -r -p
>
> The output should be the list of key-value pairs. For example,
> 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
>
> The data for selinux-policy-hash is the SHA256 hash of SELinux policy.
>
> 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
>
> cat /sys/kernel/security/integrity/ima/ascii_runtime_measurements | grep -m 1 "selinux-policy-hash" | cut -d' ' -f 6
>
> Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
> Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
> ---
> diff --git a/security/selinux/measure.c b/security/selinux/measure.c
> new file mode 100644
> index 000000000000..659011637ae7
> --- /dev/null
> +++ b/security/selinux/measure.c
> @@ -0,0 +1,155 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Measure SELinux state using IMA subsystem.
> + */
> +#include <linux/ima.h>
> +#include "security.h"
> +
> +/* Pre-allocated buffer used for measuring state */
> +static char *selinux_state_string;
> +static size_t selinux_state_string_len;
> +static char *str_format = "%s=%d;";
> +static int selinux_state_count;
> +
> +void __init selinux_init_measurement(void)
> +{
> + int i;
> +
> + /*
> + * enabled
> + * enforcing
> + * checkreqport
checkreqprot (spelling)
What about initialized? Or do you consider that to be implicitly
true/1 else we wouldn't be taking a measurement? Only caveat there is
that it provides one more means of disabling measurements (at the same
time as disabling enforcement) by setting it to false/0 via kernel
write flaw.
> + * All policy capability flags
> + */
> + selinux_state_count = 3 + __POLICYDB_CAPABILITY_MAX;
> +
> + selinux_state_string_len = snprintf(NULL, 0, str_format,
> + "enabled", 0);
> + selinux_state_string_len += snprintf(NULL, 0, str_format,
> + "enforcing", 0);
> + selinux_state_string_len += snprintf(NULL, 0, str_format,
> + "checkreqprot", 0);
> + for (i = 3; i < selinux_state_count; i++) {
> + selinux_state_string_len +=
> + snprintf(NULL, 0, str_format,
> + selinux_policycap_names[i-3], 0);
> + }
What's the benefit of this pattern versus just making the loop go from
0 to __POLICYDB_CAPABILITY_MAX and using selinux_policycap_names[i]?
> +void selinux_measure_state(struct selinux_state *selinux_state)
> +{
> + void *policy = NULL;
> + void *policy_hash = NULL;
> + size_t curr, buflen;
> + int i, policy_hash_len, rc = 0;
> +
> + if (!selinux_initialized(selinux_state)) {
> + pr_warn("%s: SELinux not yet initialized.\n", __func__);
> + return;
> + }
We could measure the global state variables before full SELinux
initialization (i.e. policy load).
Only the policy hash depends on having loaded the policy.
> +
> + if (!selinux_state_string) {
> + pr_warn("%s: Buffer for state not allocated.\n", __func__);
> + return;
> + }
> +
> + curr = snprintf(selinux_state_string, selinux_state_string_len,
> + str_format, "enabled",
> + !selinux_disabled(selinux_state));
> + curr += snprintf((selinux_state_string + curr),
> + (selinux_state_string_len - curr),
> + str_format, "enforcing",
> + enforcing_enabled(selinux_state));
> + curr += snprintf((selinux_state_string + curr),
> + (selinux_state_string_len - curr),
> + str_format, "checkreqprot",
> + selinux_checkreqprot(selinux_state));
> +
> + for (i = 3; i < selinux_state_count; i++) {
> + curr += snprintf((selinux_state_string + curr),
> + (selinux_state_string_len - curr),
> + str_format,
> + selinux_policycap_names[i - 3],
> + selinux_state->policycap[i - 3]);
> + }
Same question here as for the previous loop; seems cleaner to go from
0 to __POLICYDB_CAPABILITY_MAX and use [i].
What public git tree / branch would you recommend trying to use your
patches against? Didn't seem to apply to any of the obvious ones.
next prev parent reply other threads:[~2020-07-20 14:31 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-17 22:28 [PATCH v3 0/5] LSM: Measure security module state Lakshmi Ramasubramanian
2020-07-17 22:28 ` [PATCH v3 1/5] IMA: Add LSM_STATE func to measure LSM data Lakshmi Ramasubramanian
2020-07-17 22:28 ` [PATCH v3 2/5] IMA: Define an IMA hook " Lakshmi Ramasubramanian
2020-07-17 22:28 ` [PATCH v3 3/5] LSM: Add security_measure_data in lsm_info struct Lakshmi Ramasubramanian
2020-07-17 22:28 ` [PATCH v3 4/5] LSM: Define SELinux function to measure security state Lakshmi Ramasubramanian
2020-07-18 3:14 ` kernel test robot
2020-07-20 2:04 ` Lakshmi Ramasubramanian
2020-07-18 3:38 ` kernel test robot
2020-07-18 15:31 ` kernel test robot
2020-07-18 15:31 ` [RFC PATCH] LSM: security_read_selinux_policy() can be static kernel test robot
2020-07-20 14:31 ` Stephen Smalley [this message]
2020-07-20 15:17 ` [PATCH v3 4/5] LSM: Define SELinux function to measure security state Lakshmi Ramasubramanian
2020-07-20 17:06 ` Stephen Smalley
2020-07-20 17:26 ` Mimi Zohar
2020-07-20 17:34 ` Lakshmi Ramasubramanian
2020-07-20 17:40 ` Stephen Smalley
2020-07-20 17:49 ` Stephen Smalley
2020-07-20 18:27 ` Lakshmi Ramasubramanian
2020-07-20 18:44 ` Stephen Smalley
2020-07-20 18:59 ` Lakshmi Ramasubramanian
2020-07-17 22:28 ` [PATCH v3 5/5] LSM: Define workqueue for measuring security module state Lakshmi Ramasubramanian
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAEjxPJ7xQtZToF4d2w_o8SXFKG9kPZaWTWTFqyC-7GwBWnQa0A@mail.gmail.com \
--to=stephen.smalley.work@gmail.com \
--cc=casey@schaufler-ca.com \
--cc=jmorris@namei.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=nramas@linux.microsoft.com \
--cc=selinux@vger.kernel.org \
--cc=zohar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).