linux/security/selinux/ima.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2021 Microsoft Corporation
   4 *
   5 * Author: Lakshmi Ramasubramanian (nramas@linux.microsoft.com)
   6 *
   7 * Measure critical data structures maintainted by SELinux
   8 * using IMA subsystem.
   9 */
  10#include <linux/vmalloc.h>
  11#include <linux/ima.h>
  12#include "security.h"
  13#include "ima.h"
  14
  15/*
  16 * selinux_ima_collect_state - Read selinux configuration settings
  17 *
  18 * @state: selinux_state
  19 *
  20 * On success returns the configuration settings string.
  21 * On error, returns NULL.
  22 */
  23static char *selinux_ima_collect_state(struct selinux_state *state)
  24{
  25        const char *on = "=1;", *off = "=0;";
  26        char *buf;
  27        int buf_len, len, i, rc;
  28
  29        buf_len = strlen("initialized=0;enforcing=0;checkreqprot=0;") + 1;
  30
  31        len = strlen(on);
  32        for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++)
  33                buf_len += strlen(selinux_policycap_names[i]) + len;
  34
  35        buf = kzalloc(buf_len, GFP_KERNEL);
  36        if (!buf)
  37                return NULL;
  38
  39        rc = strscpy(buf, "initialized", buf_len);
  40        WARN_ON(rc < 0);
  41
  42        rc = strlcat(buf, selinux_initialized(state) ? on : off, buf_len);
  43        WARN_ON(rc >= buf_len);
  44
  45        rc = strlcat(buf, "enforcing", buf_len);
  46        WARN_ON(rc >= buf_len);
  47
  48        rc = strlcat(buf, enforcing_enabled(state) ? on : off, buf_len);
  49        WARN_ON(rc >= buf_len);
  50
  51        rc = strlcat(buf, "checkreqprot", buf_len);
  52        WARN_ON(rc >= buf_len);
  53
  54        rc = strlcat(buf, checkreqprot_get(state) ? on : off, buf_len);
  55        WARN_ON(rc >= buf_len);
  56
  57        for (i = 0; i < __POLICYDB_CAPABILITY_MAX; i++) {
  58                rc = strlcat(buf, selinux_policycap_names[i], buf_len);
  59                WARN_ON(rc >= buf_len);
  60
  61                rc = strlcat(buf, state->policycap[i] ? on : off, buf_len);
  62                WARN_ON(rc >= buf_len);
  63        }
  64
  65        return buf;
  66}
  67
  68/*
  69 * selinux_ima_measure_state_locked - Measure SELinux state and hash of policy
  70 *
  71 * @state: selinux state struct
  72 */
  73void selinux_ima_measure_state_locked(struct selinux_state *state)
  74{
  75        char *state_str = NULL;
  76        void *policy = NULL;
  77        size_t policy_len;
  78        int rc = 0;
  79
  80        WARN_ON(!mutex_is_locked(&state->policy_mutex));
  81
  82        state_str = selinux_ima_collect_state(state);
  83        if (!state_str) {
  84                pr_err("SELinux: %s: failed to read state.\n", __func__);
  85                return;
  86        }
  87
  88        ima_measure_critical_data("selinux", "selinux-state",
  89                                  state_str, strlen(state_str), false,
  90                                  NULL, 0);
  91
  92        kfree(state_str);
  93
  94        /*
  95         * Measure SELinux policy only after initialization is completed.
  96         */
  97        if (!selinux_initialized(state))
  98                return;
  99
 100        rc = security_read_state_kernel(state, &policy, &policy_len);
 101        if (rc) {
 102                pr_err("SELinux: %s: failed to read policy %d.\n", __func__, rc);
 103                return;
 104        }
 105
 106        ima_measure_critical_data("selinux", "selinux-policy-hash",
 107                                  policy, policy_len, true,
 108                                  NULL, 0);
 109
 110        vfree(policy);
 111}
 112
 113/*
 114 * selinux_ima_measure_state - Measure SELinux state and hash of policy
 115 *
 116 * @state: selinux state struct
 117 */
 118void selinux_ima_measure_state(struct selinux_state *state)
 119{
 120        WARN_ON(mutex_is_locked(&state->policy_mutex));
 121
 122        mutex_lock(&state->policy_mutex);
 123        selinux_ima_measure_state_locked(state);
 124        mutex_unlock(&state->policy_mutex);
 125}
 126