summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/bpf/hooks.c6
-rw-r--r--security/integrity/digsig.c8
-rw-r--r--security/integrity/digsig_asymmetric.c24
-rw-r--r--security/integrity/evm/evm_main.c9
-rw-r--r--security/integrity/ima/ima_appraise.c27
-rw-r--r--security/integrity/ima/ima_crypto.c2
-rw-r--r--security/integrity/ima/ima_fs.c10
-rw-r--r--security/integrity/ima/ima_main.c96
-rw-r--r--security/integrity/ima/ima_policy.c154
-rw-r--r--security/integrity/ima/ima_queue.c2
-rw-r--r--security/integrity/integrity_audit.c2
-rw-r--r--security/integrity/platform_certs/load_uefi.c85
-rw-r--r--security/keys/compat.c37
-rw-r--r--security/keys/internal.h5
-rw-r--r--security/keys/keyctl.c4
-rw-r--r--security/loadpin/loadpin.c17
-rw-r--r--security/security.c28
-rw-r--r--security/selinux/avc.c29
-rw-r--r--security/selinux/hooks.c25
-rw-r--r--security/selinux/include/conditional.h2
-rw-r--r--security/selinux/include/policycap.h20
-rw-r--r--security/selinux/include/policycap_names.h18
-rw-r--r--security/selinux/include/security.h63
-rw-r--r--security/selinux/selinuxfs.c259
-rw-r--r--security/selinux/ss/avtab.c49
-rw-r--r--security/selinux/ss/avtab.h1
-rw-r--r--security/selinux/ss/conditional.c155
-rw-r--r--security/selinux/ss/conditional.h2
-rw-r--r--security/selinux/ss/hashtab.c53
-rw-r--r--security/selinux/ss/hashtab.h6
-rw-r--r--security/selinux/ss/services.c875
-rw-r--r--security/selinux/ss/services.h5
-rw-r--r--security/selinux/ss/sidtab.c10
-rw-r--r--security/selinux/ss/sidtab.h2
-rw-r--r--security/smack/smack.h19
-rw-r--r--security/smack/smack_access.c55
-rw-r--r--security/smack/smack_lsm.c252
-rw-r--r--security/smack/smackfs.c23
-rw-r--r--security/tomoyo/util.c29
-rw-r--r--security/yama/yama_lsm.c2
40 files changed, 1650 insertions, 820 deletions
diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c
index 32d32d485451..788667d582ae 100644
--- a/security/bpf/hooks.c
+++ b/security/bpf/hooks.c
@@ -11,6 +11,7 @@ static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(NAME, bpf_lsm_##NAME),
#include <linux/lsm_hook_defs.h>
#undef LSM_HOOK
+ LSM_HOOK_INIT(inode_free_security, bpf_inode_storage_free),
};
static int __init bpf_lsm_init(void)
@@ -20,7 +21,12 @@ static int __init bpf_lsm_init(void)
return 0;
}
+struct lsm_blob_sizes bpf_lsm_blob_sizes __lsm_ro_after_init = {
+ .lbs_inode = sizeof(struct bpf_storage_blob),
+};
+
DEFINE_LSM(bpf) = {
.name = "bpf",
.init = bpf_lsm_init,
+ .blobs = &bpf_lsm_blob_sizes
};
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index e9cbadade74b..0f518dcfde05 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/cred.h>
+#include <linux/kernel_read_file.h>
#include <linux/key-type.h>
#include <linux/digsig.h>
#include <linux/vmalloc.h>
@@ -169,17 +170,18 @@ int __init integrity_add_key(const unsigned int id, const void *data,
int __init integrity_load_x509(const unsigned int id, const char *path)
{
- void *data;
- loff_t size;
+ void *data = NULL;
+ size_t size;
int rc;
key_perm_t perm;
- rc = kernel_read_file_from_path(path, &data, &size, 0,
+ rc = kernel_read_file_from_path(path, 0, &data, INT_MAX, NULL,
READING_X509_CERTIFICATE);
if (rc < 0) {
pr_err("Unable to open file: %s (%d)", path, rc);
return rc;
}
+ size = rc;
perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index cfa4127d0518..a662024b4c70 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -55,8 +55,14 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
}
if (IS_ERR(key)) {
- pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
- name, PTR_ERR(key));
+ if (keyring)
+ pr_err_ratelimited("Request for unknown key '%s' in '%s' keyring. err %ld\n",
+ name, keyring->description,
+ PTR_ERR(key));
+ else
+ pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
+ name, PTR_ERR(key));
+
switch (PTR_ERR(key)) {
/* Hide some search errors */
case -EACCES:
@@ -99,14 +105,22 @@ int asymmetric_verify(struct key *keyring, const char *sig,
memset(&pks, 0, sizeof(pks));
pks.hash_algo = hash_algo_name[hdr->hash_algo];
- if (hdr->hash_algo == HASH_ALGO_STREEBOG_256 ||
- hdr->hash_algo == HASH_ALGO_STREEBOG_512) {
+ switch (hdr->hash_algo) {
+ case HASH_ALGO_STREEBOG_256:
+ case HASH_ALGO_STREEBOG_512:
/* EC-RDSA and Streebog should go together. */
pks.pkey_algo = "ecrdsa";
pks.encoding = "raw";
- } else {
+ break;
+ case HASH_ALGO_SM3_256:
+ /* SM2 and SM3 should go together. */
+ pks.pkey_algo = "sm2";
+ pks.encoding = "raw";
+ break;
+ default:
pks.pkey_algo = "rsa";
pks.encoding = "pkcs1";
+ break;
}
pks.digest = (u8 *)data;
pks.digest_size = datalen;
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 0d36259b690d..76d19146d74b 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -59,6 +59,9 @@ static int __init evm_set_fixmode(char *str)
{
if (strncmp(str, "fix", 3) == 0)
evm_fixmode = 1;
+ else
+ pr_err("invalid \"%s\" mode", str);
+
return 0;
}
__setup("evm=", evm_set_fixmode);
@@ -181,6 +184,12 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
break;
case EVM_IMA_XATTR_DIGSIG:
case EVM_XATTR_PORTABLE_DIGSIG:
+ /* accept xattr with non-empty signature field */
+ if (xattr_len <= sizeof(struct signature_v2_hdr)) {
+ evm_status = INTEGRITY_FAIL;
+ goto out;
+ }
+
hdr = (struct signature_v2_hdr *)xattr_data;
digest.hdr.algo = hdr->hash_algo;
rc = evm_calc_hash(dentry, xattr_name, xattr_value,
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index b8848f53c8cc..3dd8c2e4314e 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -19,18 +19,29 @@
static int __init default_appraise_setup(char *str)
{
#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
- if (arch_ima_get_secureboot()) {
- pr_info("Secure boot enabled: ignoring ima_appraise=%s boot parameter option",
- str);
- return 1;
- }
+ bool sb_state = arch_ima_get_secureboot();
+ int appraisal_state = ima_appraise;
if (strncmp(str, "off", 3) == 0)
- ima_appraise = 0;
+ appraisal_state = 0;
else if (strncmp(str, "log", 3) == 0)
- ima_appraise = IMA_APPRAISE_LOG;
+ appraisal_state = IMA_APPRAISE_LOG;
else if (strncmp(str, "fix", 3) == 0)
- ima_appraise = IMA_APPRAISE_FIX;
+ appraisal_state = IMA_APPRAISE_FIX;
+ else if (strncmp(str, "enforce", 7) == 0)
+ appraisal_state = IMA_APPRAISE_ENFORCE;
+ else
+ pr_err("invalid \"%s\" appraise option", str);
+
+ /* If appraisal state was changed, but secure boot is enabled,
+ * keep its default */
+ if (sb_state) {
+ if (!(appraisal_state & IMA_APPRAISE_ENFORCE))
+ pr_info("Secure boot enabled: ignoring ima_appraise=%s option",
+ str);
+ } else {
+ ima_appraise = appraisal_state;
+ }
#endif
return 1;
}
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 011c3c76af86..21989fa0c107 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -829,6 +829,8 @@ static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id,
/* now accumulate with current aggregate */
rc = crypto_shash_update(shash, d.digest,
crypto_shash_digestsize(tfm));
+ if (rc != 0)
+ return rc;
}
/*
* Extend cumulative digest over TPM registers 8-9, which contain
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index e3fcad871861..ea8ff8a07b36 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -13,6 +13,7 @@
*/
#include <linux/fcntl.h>
+#include <linux/kernel_read_file.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/seq_file.h>
@@ -272,9 +273,9 @@ static const struct file_operations ima_ascii_measurements_ops = {
static ssize_t ima_read_policy(char *path)
{
- void *data;
+ void *data = NULL;
char *datap;
- loff_t size;
+ size_t size;
int rc, pathlen = strlen(path);
char *p;
@@ -283,11 +284,14 @@ static ssize_t ima_read_policy(char *path)
datap = path;
strsep(&datap, "\n");
- rc = kernel_read_file_from_path(path, &data, &size, 0, READING_POLICY);
+ rc = kernel_read_file_from_path(path, 0, &data, INT_MAX, NULL,
+ READING_POLICY);
if (rc < 0) {
pr_err("Unable to open file: %s (%d)", path, rc);
return rc;
}
+ size = rc;
+ rc = 0;
datap = data;
while (size > 0 && (p = strsep(&datap, "\n"))) {
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 8a91711ca79b..2d1af8899cab 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/file.h>
#include <linux/binfmts.h>
+#include <linux/kernel_read_file.h>
#include <linux/mount.h>
#include <linux/mman.h>
#include <linux/slab.h>
@@ -50,18 +51,23 @@ static int __init hash_setup(char *str)
return 1;
if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) {
- if (strncmp(str, "sha1", 4) == 0)
+ if (strncmp(str, "sha1", 4) == 0) {
ima_hash_algo = HASH_ALGO_SHA1;
- else if (strncmp(str, "md5", 3) == 0)
+ } else if (strncmp(str, "md5", 3) == 0) {
ima_hash_algo = HASH_ALGO_MD5;
- else
+ } else {
+ pr_err("invalid hash algorithm \"%s\" for template \"%s\"",
+ str, IMA_TEMPLATE_IMA_NAME);
return 1;
+ }
goto out;
}
i = match_string(hash_algo_name, HASH_ALGO__LAST, str);
- if (i < 0)
+ if (i < 0) {
+ pr_err("invalid hash algorithm \"%s\"", str);
return 1;
+ }
ima_hash_algo = i;
out:
@@ -531,6 +537,16 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size)
return -EOPNOTSUPP;
mutex_lock(&iint->mutex);
+
+ /*
+ * ima_file_hash can be called when ima_collect_measurement has still
+ * not been called, we might not always have a hash.
+ */
+ if (!iint->ima_hash) {
+ mutex_unlock(&iint->mutex);
+ return -EOPNOTSUPP;
+ }
+
if (buf) {
size_t copied_size;
@@ -601,6 +617,7 @@ void ima_post_path_mknod(struct dentry *dentry)
* ima_read_file - pre-measure/appraise hook decision based on policy
* @file: pointer to the file to be measured/appraised/audit
* @read_id: caller identifier
+ * @contents: whether a subsequent call will be made to ima_post_read_file()
*
* Permit reading a file based on policy. The policy rules are written
* in terms of the policy identifier. Appraising the integrity of
@@ -608,22 +625,37 @@ void ima_post_path_mknod(struct dentry *dentry)
*
* For permission return 0, otherwise return -EACCES.
*/
-int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
+int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
+ bool contents)
{
+ enum ima_hooks func;
+ u32 secid;
+
/*
- * READING_FIRMWARE_PREALLOC_BUFFER
- *
* Do devices using pre-allocated memory run the risk of the
* firmware being accessible to the device prior to the completion
* of IMA's signature verification any more than when using two
- * buffers?
+ * buffers? It may be desirable to include the buffer address
+ * in this API and walk all the dma_map_single() mappings to check.
*/
- return 0;
+
+ /*
+ * There will be a call made to ima_post_read_file() with
+ * a filled buffer, so we don't need to perform an extra
+ * read early here.
+ */
+ if (contents)
+ return 0;
+
+ /* Read entire file for all partial reads. */
+ func = read_idmap[read_id] ?: FILE_CHECK;
+ security_task_getsecid(current, &secid);
+ return process_measurement(file, current_cred(), secid, NULL,
+ 0, MAY_READ, func);
}
const int read_idmap[READING_MAX_ID] = {
[READING_FIRMWARE] = FIRMWARE_CHECK,
- [READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK,
[READING_MODULE] = MODULE_CHECK,
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
@@ -649,15 +681,6 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
enum ima_hooks func;
u32 secid;
- if (!file && read_id == READING_FIRMWARE) {
- if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
- (ima_appraise & IMA_APPRAISE_ENFORCE)) {
- pr_err("Prevent firmware loading_store.\n");
- return -EACCES; /* INTEGRITY_UNKNOWN */
- }
- return 0;
- }
-
/* permit signed certs */
if (!file && read_id == READING_X509_CERTIFICATE)
return 0;
@@ -677,6 +700,8 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
/**
* ima_load_data - appraise decision based on policy
* @id: kernel load data caller identifier
+ * @contents: whether the full contents will be available in a later
+ * call to ima_post_load_data().
*
* Callers of this LSM hook can not measure, appraise, or audit the
* data provided by userspace. Enforce policy rules requring a file
@@ -684,7 +709,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
*
* For permission return 0, otherwise return -EACCES.
*/
-int ima_load_data(enum kernel_load_data_id id)
+int ima_load_data(enum kernel_load_data_id id, bool contents)
{
bool ima_enforce, sig_enforce;
@@ -705,7 +730,7 @@ int ima_load_data(enum kernel_load_data_id id)
}
break;
case LOADING_FIRMWARE:
- if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE)) {
+ if (ima_enforce && (ima_appraise & IMA_APPRAISE_FIRMWARE) && !contents) {
pr_err("Prevent firmware sysfs fallback loading.\n");
return -EACCES; /* INTEGRITY_UNKNOWN */
}
@@ -724,6 +749,35 @@ int ima_load_data(enum kernel_load_data_id id)
return 0;
}
+/**
+ * ima_post_load_data - appraise decision based on policy
+ * @buf: pointer to in memory file contents
+ * @size: size of in memory file contents
+ * @id: kernel load data caller identifier
+ * @description: @id-specific description of contents
+ *
+ * Measure/appraise/audit in memory buffer based on policy. Policy rules
+ * are written in terms of a policy identifier.
+ *
+ * On success return 0. On integrity appraisal error, assuming the file
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
+ */
+int ima_post_load_data(char *buf, loff_t size,
+ enum kernel_load_data_id load_id,
+ char *description)
+{
+ if (load_id == LOADING_FIRMWARE) {
+ if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
+ (ima_appraise & IMA_APPRAISE_ENFORCE)) {
+ pr_err("Prevent firmware loading_store.\n");
+ return -EACCES; /* INTEGRITY_UNKNOWN */
+ }
+ return 0;
+ }
+
+ return 0;
+}
+
/*
* process_buffer_measurement - Measure the buffer to ima log.
* @inode: inode associated with the object being measured (NULL for KEY_CHECK)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index b4de33074b37..9b5adeaa47fc 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <linux/list.h>
+#include <linux/kernel_read_file.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/magic.h>
@@ -59,6 +60,11 @@ enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
+struct ima_rule_opt_list {
+ size_t count;
+ char *items[];
+};
+
struct ima_rule_entry {
struct list_head list;
int action;
@@ -78,7 +84,7 @@ struct ima_rule_entry {
int type; /* audit type */
} lsm[MAX_LSM_RULES];
char *fsname;
- char *keyrings; /* Measure keys added to these keyrings */
+ struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */
struct ima_template_desc *template;
};
@@ -206,10 +212,6 @@ static LIST_HEAD(ima_policy_rules);
static LIST_HEAD(ima_temp_rules);
static struct list_head *ima_rules = &ima_default_rules;
-/* Pre-allocated buffer used for matching keyrings. */
-static char *ima_keyrings;
-static size_t ima_keyrings_len;
-
static int ima_policy __initdata;
static int __init default_measure_policy_setup(char *str)
@@ -240,6 +242,8 @@ static int __init policy_setup(char *str)
ima_use_secure_boot = true;
else if (strcmp(p, "fail_securely") == 0)
ima_fail_unverifiable_sigs = true;
+ else
+ pr_err("policy \"%s\" not found", p);
}
return 1;
@@ -253,6 +257,72 @@ static int __init default_appraise_policy_setup(char *str)
}
__setup("ima_appraise_tcb", default_appraise_policy_setup);
+static struct ima_rule_opt_list *ima_alloc_rule_opt_list(const substring_t *src)
+{
+ struct ima_rule_opt_list *opt_list;
+ size_t count = 0;
+ char *src_copy;
+ char *cur, *next;
+ size_t i;
+
+ src_copy = match_strdup(src);
+ if (!src_copy)
+ return ERR_PTR(-ENOMEM);
+
+ next = src_copy;
+ while ((cur = strsep(&next, "|"))) {
+ /* Don't accept an empty list item */
+ if (!(*cur)) {
+ kfree(src_copy);
+ return ERR_PTR(-EINVAL);
+ }
+ count++;
+ }
+
+ /* Don't accept an empty list */
+ if (!count) {
+ kfree(src_copy);
+ return ERR_PTR(-EINVAL);
+ }
+
+ opt_list = kzalloc(struct_size(opt_list, items, count), GFP_KERNEL);
+ if (!opt_list) {
+ kfree(src_copy);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /*
+ * strsep() has already replaced all instances of '|' with '\0',
+ * leaving a byte sequence of NUL-terminated strings. Reference each
+ * string with the array of items.
+ *
+ * IMPORTANT: Ownership of the allocated buffer is transferred from
+ * src_copy to the first element in the items array. To free the
+ * buffer, kfree() must only be called on the first element of the
+ * array.
+ */
+ for (i = 0, cur = src_copy; i < count; i++) {
+ opt_list->items[i] = cur;
+ cur = strchr(cur, '\0') + 1;
+ }
+ opt_list->count = count;
+
+ return opt_list;
+}
+
+static void ima_free_rule_opt_list(struct ima_rule_opt_list *opt_list)
+{
+ if (!opt_list)
+ return;
+
+ if (opt_list->count) {
+ kfree(opt_list->items[0]);
+ opt_list->count = 0;
+ }
+
+ kfree(opt_list);
+}
+
static void ima_lsm_free_rule(struct ima_rule_entry *entry)
{
int i;
@@ -274,7 +344,7 @@ static void ima_free_rule(struct ima_rule_entry *entry)
* the defined_templates list and cannot be freed here
*/
kfree(entry->fsname);
- kfree(entry->keyrings);
+ ima_free_rule_opt_list(entry->keyrings);
ima_lsm_free_rule(entry);
kfree(entry);
}
@@ -284,15 +354,14 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
struct ima_rule_entry *nentry;
int i;
- nentry = kmalloc(sizeof(*nentry), GFP_KERNEL);
- if (!nentry)
- return NULL;
-
/*
* Immutable elements are copied over as pointers and data; only
* lsm rules can change
*/
- memcpy(nentry, entry, sizeof(*nentry));
+ nentry = kmemdup(entry, sizeof(*nentry), GFP_KERNEL);
+ if (!nentry)
+ return NULL;
+
memset(nentry->lsm, 0, sizeof_field(struct ima_rule_entry, lsm));
for (i = 0; i < MAX_LSM_RULES; i++) {
@@ -394,8 +463,8 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
static bool ima_match_keyring(struct ima_rule_entry *rule,
const char *keyring, const struct cred *cred)
{
- char *next_keyring, *keyrings_ptr;
bool matched = false;
+ size_t i;
if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
return false;
@@ -406,15 +475,8 @@ static bool ima_match_keyring(struct ima_rule_entry *rule,
if (!keyring)
return false;
- strcpy(ima_keyrings, rule->keyrings);
-
- /*
- * "keyrings=" is specified in the policy in the format below:
- * keyrings=.builtin_trusted_keys|.ima|.evm
- */
- keyrings_ptr = ima_keyrings;
- while ((next_keyring = strsep(&keyrings_ptr, "|")) != NULL) {
- if (!strcmp(next_keyring, keyring)) {
+ for (i = 0; i < rule->keyrings->count; i++) {
+ if (!strcmp(rule->keyrings->items[i], keyring)) {
matched = true;
break;
}
@@ -1065,7 +1127,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
bool uid_token;
struct ima_template_desc *template_desc;
int result = 0;
- size_t keyrings_len;
ab = integrity_audit_log_start(audit_context(), GFP_KERNEL,
AUDIT_INTEGRITY_POLICY_RULE);
@@ -1174,7 +1235,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
entry->func = POLICY_CHECK;
else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0)
entry->func = KEXEC_CMDLINE;
- else if (strcmp(args[0].from, "KEY_CHECK") == 0)
+ else if (IS_ENABLED(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) &&
+ strcmp(args[0].from, "KEY_CHECK") == 0)
entry->func = KEY_CHECK;
else
result = -EINVAL;
@@ -1231,37 +1293,19 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
case Opt_keyrings:
ima_log_string(ab, "keyrings", args[0].from);
- keyrings_len = strlen(args[0].from) + 1;
-
- if ((entry->keyrings) ||
- (keyrings_len < 2)) {
+ if (!IS_ENABLED(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) ||
+ entry->keyrings) {
result = -EINVAL;
break;
}
- if (keyrings_len > ima_keyrings_len) {
- char *tmpbuf;
-
- tmpbuf = krealloc(ima_keyrings, keyrings_len,
- GFP_KERNEL);
- if (!tmpbuf) {
- result = -ENOMEM;
- break;
- }
-
- ima_keyrings = tmpbuf;
- ima_keyrings_len = keyrings_len;
- }
-
- entry->keyrings = kstrdup(args[0].from, GFP_KERNEL);
- if (!entry->keyrings) {
- kfree(ima_keyrings);
- ima_keyrings = NULL;
- ima_keyrings_len = 0;
- result = -ENOMEM;
+ entry->keyrings = ima_alloc_rule_opt_list(args);
+ if (IS_ERR(entry->keyrings)) {
+ result = PTR_ERR(entry->keyrings);
+ entry->keyrings = NULL;
break;
}
- result = 0;
+
entry->flags |= IMA_KEYRINGS;
break;
case Opt_fsuuid:
@@ -1574,6 +1618,15 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func)
seq_printf(m, "func=%d ", func);
}
+static void ima_show_rule_opt_list(struct seq_file *m,
+ const struct ima_rule_opt_list *opt_list)
+{
+ size_t i;
+
+ for (i = 0; i < opt_list->count; i++)
+ seq_printf(m, "%s%s", i ? "|" : "", opt_list->items[i]);
+}
+
int ima_policy_show(struct seq_file *m, void *v)
{
struct ima_rule_entry *entry = v;
@@ -1630,9 +1683,8 @@ int ima_policy_show(struct seq_file *m, void *v)
}
if (entry->flags & IMA_KEYRINGS) {
- if (entry->keyrings != NULL)
- snprintf(tbuf, sizeof(tbuf), "%s", entry->keyrings);
- seq_printf(m, pt(Opt_keyrings), tbuf);
+ seq_puts(m, "keyrings=");
+ ima_show_rule_opt_list(m, entry->keyrings);
seq_puts(m, " ");
}
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index fb4ec270f620..c096ef8945c7 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -133,7 +133,7 @@ unsigned long ima_get_binary_runtime_size(void)
return ULONG_MAX;
else
return binary_runtime_size + sizeof(struct ima_kexec_hdr);
-};
+}
static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr)
{
diff --git a/security/integrity/integrity_audit.c b/security/integrity/integrity_audit.c
index f25e7df099c8..29220056207f 100644
--- a/security/integrity/integrity_audit.c
+++ b/security/integrity/integrity_audit.c
@@ -47,7 +47,7 @@ void integrity_audit_message(int audit_msgno, struct inode *inode,
ab = audit_log_start(audit_context(), GFP_KERNEL, audit_msgno);
audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u",
task_pid_nr(current),
- from_kuid(&init_user_ns, current_cred()->uid),
+ from_kuid(&init_user_ns, current_uid()),
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
audit_log_task_context(ab);
diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
index 253fb9a7fc98..ee4b4c666854 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -66,6 +66,65 @@ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
}
/*
+ * load_moklist_certs() - Load MokList certs
+ *
+ * Load the certs contained in the UEFI MokListRT database into the
+ * platform trusted keyring.
+ *
+ * This routine checks the EFI MOK config table first. If and only if
+ * that fails, this routine uses the MokListRT ordinary UEFI variable.
+ *
+ * Return: Status
+ */
+static int __init load_moklist_certs(void)
+{
+ struct efi_mokvar_table_entry *mokvar_entry;
+ efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
+ void *mok;
+ unsigned long moksize;
+ efi_status_t status;
+ int rc;
+
+ /* First try to load certs from the EFI MOKvar config table.
+ * It's not an error if the MOKv