Skip to content

Commit 840e5bb

Browse files
committed
Merge tag 'integrity-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar: "Continuing IMA policy rule cleanup and validation in particular for measuring keys, adding/removing/updating informational and error messages (e.g. "ima_appraise" boot command line option), and other bug fixes (e.g. minimal data size validation before use, return code and NULL pointer checking)" * tag 'integrity-v5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: ima: Fix NULL pointer dereference in ima_file_hash evm: Check size of security.evm before using it ima: Remove semicolon at the end of ima_get_binary_runtime_size() ima: Don't ignore errors from crypto_shash_update() ima: Use kmemdup rather than kmalloc+memcpy integrity: include keyring name for unknown key request ima: limit secure boot feedback scope for appraise integrity: invalid kernel parameters feedback ima: add check for enforced appraise option integrity: Use current_uid() in integrity_audit_message() ima: Fail rule parsing when asymmetric key measurement isn't supportable ima: Pre-parse the list of keyrings in a KEY_CHECK rule
2 parents fefa636 + aa662fc commit 840e5bb

File tree

8 files changed

+161
-67
lines changed

8 files changed

+161
-67
lines changed

security/integrity/digsig_asymmetric.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,14 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
5555
}
5656

5757
if (IS_ERR(key)) {
58-
pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
59-
name, PTR_ERR(key));
58+
if (keyring)
59+
pr_err_ratelimited("Request for unknown key '%s' in '%s' keyring. err %ld\n",
60+
name, keyring->description,
61+
PTR_ERR(key));
62+
else
63+
pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
64+
name, PTR_ERR(key));
65+
6066
switch (PTR_ERR(key)) {
6167
/* Hide some search errors */
6268
case -EACCES:

security/integrity/evm/evm_main.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ static int __init evm_set_fixmode(char *str)
5959
{
6060
if (strncmp(str, "fix", 3) == 0)
6161
evm_fixmode = 1;
62+
else
63+
pr_err("invalid \"%s\" mode", str);
64+
6265
return 0;
6366
}
6467
__setup("evm=", evm_set_fixmode);
@@ -181,6 +184,12 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
181184
break;
182185
case EVM_IMA_XATTR_DIGSIG:
183186
case EVM_XATTR_PORTABLE_DIGSIG:
187+
/* accept xattr with non-empty signature field */
188+
if (xattr_len <= sizeof(struct signature_v2_hdr)) {
189+
evm_status = INTEGRITY_FAIL;
190+
goto out;
191+
}
192+
184193
hdr = (struct signature_v2_hdr *)xattr_data;
185194
digest.hdr.algo = hdr->hash_algo;
186195
rc = evm_calc_hash(dentry, xattr_name, xattr_value,

security/integrity/ima/ima_appraise.c

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,29 @@
1919
static int __init default_appraise_setup(char *str)
2020
{
2121
#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
22-
if (arch_ima_get_secureboot()) {
23-
pr_info("Secure boot enabled: ignoring ima_appraise=%s boot parameter option",
24-
str);
25-
return 1;
26-
}
22+
bool sb_state = arch_ima_get_secureboot();
23+
int appraisal_state = ima_appraise;
2724

2825
if (strncmp(str, "off", 3) == 0)
29-
ima_appraise = 0;
26+
appraisal_state = 0;
3027
else if (strncmp(str, "log", 3) == 0)
31-
ima_appraise = IMA_APPRAISE_LOG;
28+
appraisal_state = IMA_APPRAISE_LOG;
3229
else if (strncmp(str, "fix", 3) == 0)
33-
ima_appraise = IMA_APPRAISE_FIX;
30+
appraisal_state = IMA_APPRAISE_FIX;
31+
else if (strncmp(str, "enforce", 7) == 0)
32+
appraisal_state = IMA_APPRAISE_ENFORCE;
33+
else
34+
pr_err("invalid \"%s\" appraise option", str);
35+
36+
/* If appraisal state was changed, but secure boot is enabled,
37+
* keep its default */
38+
if (sb_state) {
39+
if (!(appraisal_state & IMA_APPRAISE_ENFORCE))
40+
pr_info("Secure boot enabled: ignoring ima_appraise=%s option",
41+
str);
42+
} else {
43+
ima_appraise = appraisal_state;
44+
}
3445
#endif
3546
return 1;
3647
}

security/integrity/ima/ima_crypto.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,8 @@ static int ima_calc_boot_aggregate_tfm(char *digest, u16 alg_id,
829829
/* now accumulate with current aggregate */
830830
rc = crypto_shash_update(shash, d.digest,
831831
crypto_shash_digestsize(tfm));
832+
if (rc != 0)
833+
return rc;
832834
}
833835
/*
834836
* Extend cumulative digest over TPM registers 8-9, which contain

security/integrity/ima/ima_main.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,23 @@ static int __init hash_setup(char *str)
5151
return 1;
5252

5353
if (strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) {
54-
if (strncmp(str, "sha1", 4) == 0)
54+
if (strncmp(str, "sha1", 4) == 0) {
5555
ima_hash_algo = HASH_ALGO_SHA1;
56-
else if (strncmp(str, "md5", 3) == 0)
56+
} else if (strncmp(str, "md5", 3) == 0) {
5757
ima_hash_algo = HASH_ALGO_MD5;
58-
else
58+
} else {
59+
pr_err("invalid hash algorithm \"%s\" for template \"%s\"",
60+
str, IMA_TEMPLATE_IMA_NAME);
5961
return 1;
62+
}
6063
goto out;
6164
}
6265

6366
i = match_string(hash_algo_name, HASH_ALGO__LAST, str);
64-
if (i < 0)
67+
if (i < 0) {
68+
pr_err("invalid hash algorithm \"%s\"", str);
6569
return 1;
70+
}
6671

6772
ima_hash_algo = i;
6873
out:
@@ -532,6 +537,16 @@ int ima_file_hash(struct file *file, char *buf, size_t buf_size)
532537
return -EOPNOTSUPP;
533538

534539
mutex_lock(&iint->mutex);
540+
541+
/*
542+
* ima_file_hash can be called when ima_collect_measurement has still
543+
* not been called, we might not always have a hash.
544+
*/
545+
if (!iint->ima_hash) {
546+
mutex_unlock(&iint->mutex);
547+
return -EOPNOTSUPP;
548+
}
549+
535550
if (buf) {
536551
size_t copied_size;
537552

security/integrity/ima/ima_policy.c

Lines changed: 102 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
6060

6161
enum policy_rule_list { IMA_DEFAULT_POLICY = 1, IMA_CUSTOM_POLICY };
6262

63+
struct ima_rule_opt_list {
64+
size_t count;
65+
char *items[];
66+
};
67+
6368
struct ima_rule_entry {
6469
struct list_head list;
6570
int action;
@@ -79,7 +84,7 @@ struct ima_rule_entry {
7984
int type; /* audit type */
8085
} lsm[MAX_LSM_RULES];
8186
char *fsname;
82-
char *keyrings; /* Measure keys added to these keyrings */
87+
struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */
8388
struct ima_template_desc *template;
8489
};
8590

@@ -207,10 +212,6 @@ static LIST_HEAD(ima_policy_rules);
207212
static LIST_HEAD(ima_temp_rules);
208213
static struct list_head *ima_rules = &ima_default_rules;
209214

210-
/* Pre-allocated buffer used for matching keyrings. */
211-
static char *ima_keyrings;
212-
static size_t ima_keyrings_len;
213-
214215
static int ima_policy __initdata;
215216

216217
static int __init default_measure_policy_setup(char *str)
@@ -241,6 +242,8 @@ static int __init policy_setup(char *str)
241242
ima_use_secure_boot = true;
242243
else if (strcmp(p, "fail_securely") == 0)
243244
ima_fail_unverifiable_sigs = true;
245+
else
246+
pr_err("policy \"%s\" not found", p);
244247
}
245248

246249
return 1;
@@ -254,6 +257,72 @@ static int __init default_appraise_policy_setup(char *str)
254257
}
255258
__setup("ima_appraise_tcb", default_appraise_policy_setup);
256259

260+
static struct ima_rule_opt_list *ima_alloc_rule_opt_list(const substring_t *src)
261+
{
262+
struct ima_rule_opt_list *opt_list;
263+
size_t count = 0;
264+
char *src_copy;
265+
char *cur, *next;
266+
size_t i;
267+
268+
src_copy = match_strdup(src);
269+
if (!src_copy)
270+
return ERR_PTR(-ENOMEM);
271+
272+
next = src_copy;
273+
while ((cur = strsep(&next, "|"))) {
274+
/* Don't accept an empty list item */
275+
if (!(*cur)) {
276+
kfree(src_copy);
277+
return ERR_PTR(-EINVAL);
278+
}
279+
count++;
280+
}
281+
282+
/* Don't accept an empty list */
283+
if (!count) {
284+
kfree(src_copy);
285+
return ERR_PTR(-EINVAL);
286+
}
287+
288+
opt_list = kzalloc(struct_size(opt_list, items, count), GFP_KERNEL);
289+
if (!opt_list) {
290+
kfree(src_copy);
291+
return ERR_PTR(-ENOMEM);
292+
}
293+
294+
/*
295+
* strsep() has already replaced all instances of '|' with '\0',
296+
* leaving a byte sequence of NUL-terminated strings. Reference each
297+
* string with the array of items.
298+
*
299+
* IMPORTANT: Ownership of the allocated buffer is transferred from
300+
* src_copy to the first element in the items array. To free the
301+
* buffer, kfree() must only be called on the first element of the
302+
* array.
303+
*/
304+
for (i = 0, cur = src_copy; i < count; i++) {
305+
opt_list->items[i] = cur;
306+
cur = strchr(cur, '\0') + 1;
307+
}
308+
opt_list->count = count;
309+
310+
return opt_list;
311+
}
312+
313+
static void ima_free_rule_opt_list(struct ima_rule_opt_list *opt_list)
314+
{
315+
if (!opt_list)
316+
return;
317+
318+
if (opt_list->count) {
319+
kfree(opt_list->items[0]);
320+
opt_list->count = 0;
321+
}
322+
323+
kfree(opt_list);
324+
}
325+
257326
static void ima_lsm_free_rule(struct ima_rule_entry *entry)
258327
{
259328
int i;
@@ -275,7 +344,7 @@ static void ima_free_rule(struct ima_rule_entry *entry)
275344
* the defined_templates list and cannot be freed here
276345
*/
277346
kfree(entry->fsname);
278-
kfree(entry->keyrings);
347+
ima_free_rule_opt_list(entry->keyrings);
279348
ima_lsm_free_rule(entry);
280349
kfree(entry);
281350
}
@@ -285,15 +354,14 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
285354
struct ima_rule_entry *nentry;
286355
int i;
287356

288-
nentry = kmalloc(sizeof(*nentry), GFP_KERNEL);
289-
if (!nentry)
290-
return NULL;
291-
292357
/*
293358
* Immutable elements are copied over as pointers and data; only
294359
* lsm rules can change
295360
*/
296-
memcpy(nentry, entry, sizeof(*nentry));
361+
nentry = kmemdup(entry, sizeof(*nentry), GFP_KERNEL);
362+
if (!nentry)
363+
return NULL;
364+
297365
memset(nentry->lsm, 0, sizeof_field(struct ima_rule_entry, lsm));
298366

299367
for (i = 0; i < MAX_LSM_RULES; i++) {
@@ -395,8 +463,8 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
395463
static bool ima_match_keyring(struct ima_rule_entry *rule,
396464
const char *keyring, const struct cred *cred)
397465
{
398-
char *next_keyring, *keyrings_ptr;
399466
bool matched = false;
467+
size_t i;
400468

401469
if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
402470
return false;
@@ -407,15 +475,8 @@ static bool ima_match_keyring(struct ima_rule_entry *rule,
407475
if (!keyring)
408476
return false;
409477

410-
strcpy(ima_keyrings, rule->keyrings);
411-
412-
/*
413-
* "keyrings=" is specified in the policy in the format below:
414-
* keyrings=.builtin_trusted_keys|.ima|.evm
415-
*/
416-
keyrings_ptr = ima_keyrings;
417-
while ((next_keyring = strsep(&keyrings_ptr, "|")) != NULL) {
418-
if (!strcmp(next_keyring, keyring)) {
478+
for (i = 0; i < rule->keyrings->count; i++) {
479+
if (!strcmp(rule->keyrings->items[i], keyring)) {
419480
matched = true;
420481
break;
421482
}
@@ -1066,7 +1127,6 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
10661127
bool uid_token;
10671128
struct ima_template_desc *template_desc;
10681129
int result = 0;
1069-
size_t keyrings_len;
10701130

10711131
ab = integrity_audit_log_start(audit_context(), GFP_KERNEL,
10721132
AUDIT_INTEGRITY_POLICY_RULE);
@@ -1175,7 +1235,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
11751235
entry->func = POLICY_CHECK;
11761236
else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0)
11771237
entry->func = KEXEC_CMDLINE;
1178-
else if (strcmp(args[0].from, "KEY_CHECK") == 0)
1238+
else if (IS_ENABLED(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) &&
1239+
strcmp(args[0].from, "KEY_CHECK") == 0)
11791240
entry->func = KEY_CHECK;
11801241
else
11811242
result = -EINVAL;
@@ -1232,37 +1293,19 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
12321293
case Opt_keyrings:
12331294
ima_log_string(ab, "keyrings", args[0].from);
12341295

1235-
keyrings_len = strlen(args[0].from) + 1;
1236-
1237-
if ((entry->keyrings) ||
1238-
(keyrings_len < 2)) {
1296+
if (!IS_ENABLED(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) ||
1297+
entry->keyrings) {
12391298
result = -EINVAL;
12401299
break;
12411300
}
12421301

1243-
if (keyrings_len > ima_keyrings_len) {
1244-
char *tmpbuf;
1245-
1246-
tmpbuf = krealloc(ima_keyrings, keyrings_len,
1247-
GFP_KERNEL);
1248-
if (!tmpbuf) {
1249-
result = -ENOMEM;
1250-
break;
1251-
}
1252-
1253-
ima_keyrings = tmpbuf;
1254-
ima_keyrings_len = keyrings_len;
1255-
}
1256-
1257-
entry->keyrings = kstrdup(args[0].from, GFP_KERNEL);
1258-
if (!entry->keyrings) {
1259-
kfree(ima_keyrings);
1260-
ima_keyrings = NULL;
1261-
ima_keyrings_len = 0;
1262-
result = -ENOMEM;
1302+
entry->keyrings = ima_alloc_rule_opt_list(args);
1303+
if (IS_ERR(entry->keyrings)) {
1304+
result = PTR_ERR(entry->keyrings);
1305+
entry->keyrings = NULL;
12631306
break;
12641307
}
1265-
result = 0;
1308+
12661309
entry->flags |= IMA_KEYRINGS;
12671310
break;
12681311
case Opt_fsuuid:
@@ -1575,6 +1618,15 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func)
15751618
seq_printf(m, "func=%d ", func);
15761619
}
15771620

1621+
static void ima_show_rule_opt_list(struct seq_file *m,
1622+
const struct ima_rule_opt_list *opt_list)
1623+
{
1624+
size_t i;
1625+
1626+
for (i = 0; i < opt_list->count; i++)
1627+
seq_printf(m, "%s%s", i ? "|" : "", opt_list->items[i]);
1628+
}
1629+
15781630
int ima_policy_show(struct seq_file *m, void *v)
15791631
{
15801632
struct ima_rule_entry *entry = v;
@@ -1631,9 +1683,8 @@ int ima_policy_show(struct seq_file *m, void *v)
16311683
}
16321684

16331685
if (entry->flags & IMA_KEYRINGS) {
1634-
if (entry->keyrings != NULL)
1635-
snprintf(tbuf, sizeof(tbuf), "%s", entry->keyrings);
1636-
seq_printf(m, pt(Opt_keyrings), tbuf);
1686+
seq_puts(m, "keyrings=");
1687+
ima_show_rule_opt_list(m, entry->keyrings);
16371688
seq_puts(m, " ");
16381689
}
16391690

0 commit comments

Comments
 (0)