Skip to content

Commit 777f817

Browse files
committed
Merge tag 'integrity-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar: "Bug fixes: - defer credentials checking from the bprm_check_security hook to the bprm_creds_from_file security hook - properly ignore IMA policy rules based on undefined SELinux labels IMA policy rule extensions: - extend IMA to limit including file hashes in the audit logs (dont_audit action) - define a new filesystem subtype policy option (fs_subtype) Misc: - extend IMA to support in-kernel module decompression by deferring the IMA signature verification in kernel_read_file() to after the kernel module is decompressed" * tag 'integrity-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: ima: Handle error code returned by ima_filter_rule_match() ima: Access decompressed kernel module to verify appended signature ima: add fs_subtype condition for distinguishing FUSE instances ima: add dont_audit action to suppress audit actions ima: Attach CREDS_CHECK IMA hook to bprm_creds_from_file LSM hook
2 parents 204a920 + 738c973 commit 777f817

7 files changed

Lines changed: 123 additions & 28 deletions

File tree

Documentation/ABI/testing/ima_policy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ Description:
2020
rule format: action [condition ...]
2121

2222
action: measure | dont_measure | appraise | dont_appraise |
23-
audit | hash | dont_hash
23+
audit | dont_audit | hash | dont_hash
2424
condition:= base | lsm [option]
2525
base: [[func=] [mask=] [fsmagic=] [fsuuid=] [fsname=]
26+
[fs_subtype=]
2627
[uid=] [euid=] [gid=] [egid=]
2728
[fowner=] [fgroup=]]
2829
lsm: [[subj_user=] [subj_role=] [subj_type=]

include/linux/kernel_read_file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
id(KEXEC_INITRAMFS, kexec-initramfs) \
1515
id(POLICY, security-policy) \
1616
id(X509_CERTIFICATE, x509-certificate) \
17+
id(MODULE_COMPRESSED, kernel-module-compressed) \
1718
id(MAX_ID, )
1819

1920
#define __fid_enumify(ENUM, dummy) READING_ ## ENUM,

kernel/module/main.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3675,24 +3675,35 @@ static int idempotent_wait_for_completion(struct idempotent *u)
36753675

36763676
static int init_module_from_file(struct file *f, const char __user * uargs, int flags)
36773677
{
3678+
bool compressed = !!(flags & MODULE_INIT_COMPRESSED_FILE);
36783679
struct load_info info = { };
36793680
void *buf = NULL;
36803681
int len;
3682+
int err;
36813683

3682-
len = kernel_read_file(f, 0, &buf, INT_MAX, NULL, READING_MODULE);
3684+
len = kernel_read_file(f, 0, &buf, INT_MAX, NULL,
3685+
compressed ? READING_MODULE_COMPRESSED :
3686+
READING_MODULE);
36833687
if (len < 0) {
36843688
mod_stat_inc(&failed_kreads);
36853689
return len;
36863690
}
36873691

3688-
if (flags & MODULE_INIT_COMPRESSED_FILE) {
3689-
int err = module_decompress(&info, buf, len);
3692+
if (compressed) {
3693+
err = module_decompress(&info, buf, len);
36903694
vfree(buf); /* compressed data is no longer needed */
36913695
if (err) {
36923696
mod_stat_inc(&failed_decompress);
36933697
mod_stat_add_long(len, &invalid_decompress_bytes);
36943698
return err;
36953699
}
3700+
err = security_kernel_post_read_file(f, (char *)info.hdr, info.len,
3701+
READING_MODULE);
3702+
if (err) {
3703+
mod_stat_inc(&failed_kreads);
3704+
free_copy(&info, flags);
3705+
return err;
3706+
}
36963707
} else {
36973708
info.hdr = buf;
36983709
info.len = len;

security/integrity/ima/ima_main.c

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ static void ima_file_free(struct file *file)
235235

236236
static int process_measurement(struct file *file, const struct cred *cred,
237237
struct lsm_prop *prop, char *buf, loff_t size,
238-
int mask, enum ima_hooks func)
238+
int mask, enum ima_hooks func,
239+
enum kernel_read_file_id read_id)
239240
{
240241
struct inode *real_inode, *inode = file_inode(file);
241242
struct ima_iint_cache *iint = NULL;
@@ -406,6 +407,12 @@ static int process_measurement(struct file *file, const struct cred *cred,
406407
if (rc != 0 && rc != -EBADF && rc != -EINVAL)
407408
goto out_locked;
408409

410+
/* Defer measuring/appraising kernel modules to READING_MODULE */
411+
if (read_id == READING_MODULE_COMPRESSED) {
412+
must_appraise = 0;
413+
goto out_locked;
414+
}
415+
409416
if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */
410417
pathname = ima_d_path(&file->f_path, &pathbuf, filename);
411418

@@ -486,14 +493,14 @@ static int ima_file_mmap(struct file *file, unsigned long reqprot,
486493

487494
if (reqprot & PROT_EXEC) {
488495
ret = process_measurement(file, current_cred(), &prop, NULL,
489-
0, MAY_EXEC, MMAP_CHECK_REQPROT);
496+
0, MAY_EXEC, MMAP_CHECK_REQPROT, 0);
490497
if (ret)
491498
return ret;
492499
}
493500

494501
if (prot & PROT_EXEC)
495502
return process_measurement(file, current_cred(), &prop, NULL,
496-
0, MAY_EXEC, MMAP_CHECK);
503+
0, MAY_EXEC, MMAP_CHECK, 0);
497504

498505
return 0;
499506
}
@@ -573,18 +580,41 @@ static int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
573580
*/
574581
static int ima_bprm_check(struct linux_binprm *bprm)
575582
{
576-
int ret;
577583
struct lsm_prop prop;
578584

579585
security_current_getlsmprop_subj(&prop);
580-
ret = process_measurement(bprm->file, current_cred(),
581-
&prop, NULL, 0, MAY_EXEC, BPRM_CHECK);
582-
if (ret)
583-
return ret;
584-
585-
security_cred_getlsmprop(bprm->cred, &prop);
586-
return process_measurement(bprm->file, bprm->cred, &prop, NULL, 0,
587-
MAY_EXEC, CREDS_CHECK);
586+
return process_measurement(bprm->file, current_cred(),
587+
&prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0);
588+
}
589+
590+
/**
591+
* ima_creds_check - based on policy, collect/store measurement.
592+
* @bprm: contains the linux_binprm structure
593+
* @file: contains the file descriptor of the binary being executed
594+
*
595+
* The OS protects against an executable file, already open for write,
596+
* from being executed in deny_write_access() and an executable file,
597+
* already open for execute, from being modified in get_write_access().
598+
* So we can be certain that what we verify and measure here is actually
599+
* what is being executed.
600+
*
601+
* The difference from ima_bprm_check() is that ima_creds_check() is invoked
602+
* only after determining the final binary to be executed without interpreter,
603+
* and not when searching for intermediate binaries. The reason is that since
604+
* commit 56305aa9b6fab ("exec: Compute file based creds only once"), the
605+
* credentials to be applied to the process are calculated only at that stage
606+
* (bprm_creds_from_file security hook instead of bprm_check_security).
607+
*
608+
* On success return 0. On integrity appraisal error, assuming the file
609+
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
610+
*/
611+
static int ima_creds_check(struct linux_binprm *bprm, const struct file *file)
612+
{
613+
struct lsm_prop prop;
614+
615+
security_current_getlsmprop_subj(&prop);
616+
return process_measurement((struct file *)file, bprm->cred, &prop, NULL,
617+
0, MAY_EXEC, CREDS_CHECK, 0);
588618
}
589619

590620
/**
@@ -632,7 +662,7 @@ static int ima_file_check(struct file *file, int mask)
632662
security_current_getlsmprop_subj(&prop);
633663
return process_measurement(file, current_cred(), &prop, NULL, 0,
634664
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
635-
MAY_APPEND), FILE_CHECK);
665+
MAY_APPEND), FILE_CHECK, 0);
636666
}
637667

638668
static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
@@ -851,12 +881,13 @@ static int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
851881
func = read_idmap[read_id] ?: FILE_CHECK;
852882
security_current_getlsmprop_subj(&prop);
853883
return process_measurement(file, current_cred(), &prop, NULL, 0,
854-
MAY_READ, func);
884+
MAY_READ, func, 0);
855885
}
856886

857887
const int read_idmap[READING_MAX_ID] = {
858888
[READING_FIRMWARE] = FIRMWARE_CHECK,
859889
[READING_MODULE] = MODULE_CHECK,
890+
[READING_MODULE_COMPRESSED] = MODULE_CHECK,
860891
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
861892
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
862893
[READING_POLICY] = POLICY_CHECK
@@ -894,7 +925,7 @@ static int ima_post_read_file(struct file *file, char *buf, loff_t size,
894925
func = read_idmap[read_id] ?: FILE_CHECK;
895926
security_current_getlsmprop_subj(&prop);
896927
return process_measurement(file, current_cred(), &prop, buf, size,
897-
MAY_READ, func);
928+
MAY_READ, func, read_id);
898929
}
899930

900931
/**
@@ -1242,6 +1273,7 @@ static int __init init_ima(void)
12421273
static struct security_hook_list ima_hooks[] __ro_after_init = {
12431274
LSM_HOOK_INIT(bprm_check_security, ima_bprm_check),
12441275
LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec),
1276+
LSM_HOOK_INIT(bprm_creds_from_file, ima_creds_check),
12451277
LSM_HOOK_INIT(file_post_open, ima_file_check),
12461278
LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile),
12471279
LSM_HOOK_INIT(file_release, ima_file_free),

security/integrity/ima/ima_policy.c

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@
3838
#define IMA_GID 0x2000
3939
#define IMA_EGID 0x4000
4040
#define IMA_FGROUP 0x8000
41+
#define IMA_FS_SUBTYPE 0x10000
4142

4243
#define UNKNOWN 0
4344
#define MEASURE 0x0001 /* same as IMA_MEASURE */
4445
#define DONT_MEASURE 0x0002
4546
#define APPRAISE 0x0004 /* same as IMA_APPRAISE */
4647
#define DONT_APPRAISE 0x0008
4748
#define AUDIT 0x0040
49+
#define DONT_AUDIT 0x0080
4850
#define HASH 0x0100
4951
#define DONT_HASH 0x0200
5052

@@ -119,6 +121,7 @@ struct ima_rule_entry {
119121
int type; /* audit type */
120122
} lsm[MAX_LSM_RULES];
121123
char *fsname;
124+
char *fs_subtype;
122125
struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */
123126
struct ima_rule_opt_list *label; /* Measure data grouped under this label */
124127
struct ima_template_desc *template;
@@ -241,7 +244,8 @@ static struct ima_rule_entry build_appraise_rules[] __ro_after_init = {
241244

242245
static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
243246
{.action = APPRAISE, .func = MODULE_CHECK,
244-
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
247+
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED |
248+
IMA_CHECK_BLACKLIST},
245249
{.action = APPRAISE, .func = FIRMWARE_CHECK,
246250
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
247251
{.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
@@ -397,6 +401,7 @@ static void ima_free_rule(struct ima_rule_entry *entry)
397401
* the defined_templates list and cannot be freed here
398402
*/
399403
kfree(entry->fsname);
404+
kfree(entry->fs_subtype);
400405
ima_free_rule_opt_list(entry->keyrings);
401406
ima_lsm_free_rule(entry);
402407
kfree(entry);
@@ -601,6 +606,12 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
601606
if ((rule->flags & IMA_FSNAME)
602607
&& strcmp(rule->fsname, inode->i_sb->s_type->name))
603608
return false;
609+
if (rule->flags & IMA_FS_SUBTYPE) {
610+
if (!inode->i_sb->s_subtype)
611+
return false;
612+
if (strcmp(rule->fs_subtype, inode->i_sb->s_subtype))
613+
return false;
614+
}
604615
if ((rule->flags & IMA_FSUUID) &&
605616
!uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
606617
return false;
@@ -674,7 +685,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
674685
goto retry;
675686
}
676687
}
677-
if (!rc) {
688+
if (rc <= 0) {
678689
result = false;
679690
goto out;
680691
}
@@ -1064,10 +1075,10 @@ void ima_update_policy(void)
10641075
enum policy_opt {
10651076
Opt_measure, Opt_dont_measure,
10661077
Opt_appraise, Opt_dont_appraise,
1067-
Opt_audit, Opt_hash, Opt_dont_hash,
1078+
Opt_audit, Opt_dont_audit, Opt_hash, Opt_dont_hash,
10681079
Opt_obj_user, Opt_obj_role, Opt_obj_type,
10691080
Opt_subj_user, Opt_subj_role, Opt_subj_type,
1070-
Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname, Opt_fsuuid,
1081+
Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname, Opt_fs_subtype, Opt_fsuuid,
10711082
Opt_uid_eq, Opt_euid_eq, Opt_gid_eq, Opt_egid_eq,
10721083
Opt_fowner_eq, Opt_fgroup_eq,
10731084
Opt_uid_gt, Opt_euid_gt, Opt_gid_gt, Opt_egid_gt,
@@ -1086,6 +1097,7 @@ static const match_table_t policy_tokens = {
10861097
{Opt_appraise, "appraise"},
10871098
{Opt_dont_appraise, "dont_appraise"},
10881099
{Opt_audit, "audit"},
1100+
{Opt_dont_audit, "dont_audit"},
10891101
{Opt_hash, "hash"},
10901102
{Opt_dont_hash, "dont_hash"},
10911103
{Opt_obj_user, "obj_user=%s"},
@@ -1098,6 +1110,7 @@ static const match_table_t policy_tokens = {
10981110
{Opt_mask, "mask=%s"},
10991111
{Opt_fsmagic, "fsmagic=%s"},
11001112
{Opt_fsname, "fsname=%s"},
1113+
{Opt_fs_subtype, "fs_subtype=%s"},
11011114
{Opt_fsuuid, "fsuuid=%s"},
11021115
{Opt_uid_eq, "uid=%s"},
11031116
{Opt_euid_eq, "euid=%s"},
@@ -1282,7 +1295,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
12821295
if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
12831296
IMA_UID | IMA_FOWNER | IMA_FSUUID |
12841297
IMA_INMASK | IMA_EUID | IMA_PCR |
1285-
IMA_FSNAME | IMA_GID | IMA_EGID |
1298+
IMA_FSNAME | IMA_FS_SUBTYPE |
1299+
IMA_GID | IMA_EGID |
12861300
IMA_FGROUP | IMA_DIGSIG_REQUIRED |
12871301
IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS |
12881302
IMA_CHECK_BLACKLIST | IMA_VERITY_REQUIRED))
@@ -1295,7 +1309,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
12951309
if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
12961310
IMA_UID | IMA_FOWNER | IMA_FSUUID |
12971311
IMA_INMASK | IMA_EUID | IMA_PCR |
1298-
IMA_FSNAME | IMA_GID | IMA_EGID |
1312+
IMA_FSNAME | IMA_FS_SUBTYPE |
1313+
IMA_GID | IMA_EGID |
12991314
IMA_FGROUP | IMA_DIGSIG_REQUIRED |
13001315
IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED |
13011316
IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
@@ -1308,7 +1323,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
13081323

13091324
if (entry->flags & ~(IMA_FUNC | IMA_FSMAGIC | IMA_UID |
13101325
IMA_FOWNER | IMA_FSUUID | IMA_EUID |
1311-
IMA_PCR | IMA_FSNAME | IMA_GID | IMA_EGID |
1326+
IMA_PCR | IMA_FSNAME | IMA_FS_SUBTYPE |
1327+
IMA_GID | IMA_EGID |
13121328
IMA_FGROUP))
13131329
return false;
13141330

@@ -1478,6 +1494,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
14781494

14791495
entry->action = AUDIT;
14801496
break;
1497+
case Opt_dont_audit:
1498+
ima_log_string(ab, "action", "dont_audit");
1499+
1500+
if (entry->action != UNKNOWN)
1501+
result = -EINVAL;
1502+
1503+
entry->action = DONT_AUDIT;
1504+
break;
14811505
case Opt_hash:
14821506
ima_log_string(ab, "action", "hash");
14831507

@@ -1587,6 +1611,22 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
15871611
result = 0;
15881612
entry->flags |= IMA_FSNAME;
15891613
break;
1614+
case Opt_fs_subtype:
1615+
ima_log_string(ab, "fs_subtype", args[0].from);
1616+
1617+
if (entry->fs_subtype) {
1618+
result = -EINVAL;
1619+
break;
1620+
}
1621+
1622+
entry->fs_subtype = kstrdup(args[0].from, GFP_KERNEL);
1623+
if (!entry->fs_subtype) {
1624+
result = -ENOMEM;
1625+
break;
1626+
}
1627+
result = 0;
1628+
entry->flags |= IMA_FS_SUBTYPE;
1629+
break;
15901630
case Opt_keyrings:
15911631
ima_log_string(ab, "keyrings", args[0].from);
15921632

@@ -2097,6 +2137,8 @@ int ima_policy_show(struct seq_file *m, void *v)
20972137
seq_puts(m, pt(Opt_dont_appraise));
20982138
if (entry->action & AUDIT)
20992139
seq_puts(m, pt(Opt_audit));
2140+
if (entry->action & DONT_AUDIT)
2141+
seq_puts(m, pt(Opt_dont_audit));
21002142
if (entry->action & HASH)
21012143
seq_puts(m, pt(Opt_hash));
21022144
if (entry->action & DONT_HASH)
@@ -2133,6 +2175,12 @@ int ima_policy_show(struct seq_file *m, void *v)
21332175
seq_puts(m, " ");
21342176
}
21352177

2178+
if (entry->flags & IMA_FS_SUBTYPE) {
2179+
snprintf(tbuf, sizeof(tbuf), "%s", entry->fs_subtype);
2180+
seq_printf(m, pt(Opt_fs_subtype), tbuf);
2181+
seq_puts(m, " ");
2182+
}
2183+
21362184
if (entry->flags & IMA_KEYRINGS) {
21372185
seq_puts(m, "keyrings=");
21382186
ima_show_rule_opt_list(m, entry->keyrings);

security/ipe/hooks.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
118118
op = IPE_OP_FIRMWARE;
119119
break;
120120
case READING_MODULE:
121+
case READING_MODULE_COMPRESSED:
121122
op = IPE_OP_KERNEL_MODULE;
122123
break;
123124
case READING_KEXEC_INITRAMFS:

0 commit comments

Comments
 (0)