Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ima: Access decompressed kernel module to verify appended signature

Currently, when in-kernel module decompression (CONFIG_MODULE_DECOMPRESS)
is enabled, IMA has no way to verify the appended module signature as it
can't decompress the module.

Define a new kernel_read_file_id enumerate READING_MODULE_COMPRESSED so
IMA can calculate the compressed kernel module data hash on
READING_MODULE_COMPRESSED and defer appraising/measuring it until on
READING_MODULE when the module has been decompressed.

Before enabling in-kernel module decompression, a kernel module in
initramfs can still be loaded with ima_policy=secure_boot. So adjust the
kernel module rule in secure_boot policy to allow either an IMA
signature OR an appended signature i.e. to use
"appraise func=MODULE_CHECK appraise_type=imasig|modsig".

Reported-by: Karel Srot <ksrot@redhat.com>
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
Suggested-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Coiby Xu <coxu@redhat.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>

authored by

Coiby Xu and committed by
Mimi Zohar
c200892b 43369273

+37 -14
+1
include/linux/kernel_read_file.h
··· 14 14 id(KEXEC_INITRAMFS, kexec-initramfs) \ 15 15 id(POLICY, security-policy) \ 16 16 id(X509_CERTIFICATE, x509-certificate) \ 17 + id(MODULE_COMPRESSED, kernel-module-compressed) \ 17 18 id(MAX_ID, ) 18 19 19 20 #define __fid_enumify(ENUM, dummy) READING_ ## ENUM,
+14 -3
kernel/module/main.c
··· 3675 3675 3676 3676 static int init_module_from_file(struct file *f, const char __user * uargs, int flags) 3677 3677 { 3678 + bool compressed = !!(flags & MODULE_INIT_COMPRESSED_FILE); 3678 3679 struct load_info info = { }; 3679 3680 void *buf = NULL; 3680 3681 int len; 3682 + int err; 3681 3683 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); 3683 3687 if (len < 0) { 3684 3688 mod_stat_inc(&failed_kreads); 3685 3689 return len; 3686 3690 } 3687 3691 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); 3690 3694 vfree(buf); /* compressed data is no longer needed */ 3691 3695 if (err) { 3692 3696 mod_stat_inc(&failed_decompress); 3693 3697 mod_stat_add_long(len, &invalid_decompress_bytes); 3698 + return err; 3699 + } 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); 3694 3705 return err; 3695 3706 } 3696 3707 } else {
+16 -8
security/integrity/ima/ima_main.c
··· 235 235 236 236 static int process_measurement(struct file *file, const struct cred *cred, 237 237 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) 239 240 { 240 241 struct inode *real_inode, *inode = file_inode(file); 241 242 struct ima_iint_cache *iint = NULL; ··· 407 406 if (rc != 0 && rc != -EBADF && rc != -EINVAL) 408 407 goto out_locked; 409 408 409 + /* Defer measuring/appraising kernel modules to READING_MODULE */ 410 + if (read_id == READING_MODULE_COMPRESSED) { 411 + must_appraise = 0; 412 + goto out_locked; 413 + } 414 + 410 415 if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */ 411 416 pathname = ima_d_path(&file->f_path, &pathbuf, filename); 412 417 ··· 493 486 494 487 if (reqprot & PROT_EXEC) { 495 488 ret = process_measurement(file, current_cred(), &prop, NULL, 496 - 0, MAY_EXEC, MMAP_CHECK_REQPROT); 489 + 0, MAY_EXEC, MMAP_CHECK_REQPROT, 0); 497 490 if (ret) 498 491 return ret; 499 492 } 500 493 501 494 if (prot & PROT_EXEC) 502 495 return process_measurement(file, current_cred(), &prop, NULL, 503 - 0, MAY_EXEC, MMAP_CHECK); 496 + 0, MAY_EXEC, MMAP_CHECK, 0); 504 497 505 498 return 0; 506 499 } ··· 584 577 585 578 security_current_getlsmprop_subj(&prop); 586 579 return process_measurement(bprm->file, current_cred(), 587 - &prop, NULL, 0, MAY_EXEC, BPRM_CHECK); 580 + &prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0); 588 581 } 589 582 590 583 /** ··· 614 607 615 608 security_current_getlsmprop_subj(&prop); 616 609 return process_measurement((struct file *)file, bprm->cred, &prop, NULL, 617 - 0, MAY_EXEC, CREDS_CHECK); 610 + 0, MAY_EXEC, CREDS_CHECK, 0); 618 611 } 619 612 620 613 /** ··· 662 655 security_current_getlsmprop_subj(&prop); 663 656 return process_measurement(file, current_cred(), &prop, NULL, 0, 664 657 mask & (MAY_READ | MAY_WRITE | MAY_EXEC | 665 - MAY_APPEND), FILE_CHECK); 658 + MAY_APPEND), FILE_CHECK, 0); 666 659 } 667 660 668 661 static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf, ··· 881 874 func = read_idmap[read_id] ?: FILE_CHECK; 882 875 security_current_getlsmprop_subj(&prop); 883 876 return process_measurement(file, current_cred(), &prop, NULL, 0, 884 - MAY_READ, func); 877 + MAY_READ, func, 0); 885 878 } 886 879 887 880 const int read_idmap[READING_MAX_ID] = { 888 881 [READING_FIRMWARE] = FIRMWARE_CHECK, 889 882 [READING_MODULE] = MODULE_CHECK, 883 + [READING_MODULE_COMPRESSED] = MODULE_CHECK, 890 884 [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, 891 885 [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, 892 886 [READING_POLICY] = POLICY_CHECK ··· 925 917 func = read_idmap[read_id] ?: FILE_CHECK; 926 918 security_current_getlsmprop_subj(&prop); 927 919 return process_measurement(file, current_cred(), &prop, buf, size, 928 - MAY_READ, func); 920 + MAY_READ, func, read_id); 929 921 } 930 922 931 923 /**
+2 -1
security/integrity/ima/ima_policy.c
··· 244 244 245 245 static struct ima_rule_entry secure_boot_rules[] __ro_after_init = { 246 246 {.action = APPRAISE, .func = MODULE_CHECK, 247 - .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 247 + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED | 248 + IMA_CHECK_BLACKLIST}, 248 249 {.action = APPRAISE, .func = FIRMWARE_CHECK, 249 250 .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, 250 251 {.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
+1
security/ipe/hooks.c
··· 118 118 op = IPE_OP_FIRMWARE; 119 119 break; 120 120 case READING_MODULE: 121 + case READING_MODULE_COMPRESSED: 121 122 op = IPE_OP_KERNEL_MODULE; 122 123 break; 123 124 case READING_KEXEC_INITRAMFS:
+3 -2
security/selinux/hooks.c
··· 4275 4275 { 4276 4276 int rc = 0; 4277 4277 4278 - BUILD_BUG_ON_MSG(READING_MAX_ID > 7, 4278 + BUILD_BUG_ON_MSG(READING_MAX_ID > 8, 4279 4279 "New kernel_read_file_id introduced; update SELinux!"); 4280 4280 4281 4281 switch (id) { ··· 4283 4283 rc = selinux_kernel_load_from_file(file, SYSTEM__FIRMWARE_LOAD); 4284 4284 break; 4285 4285 case READING_MODULE: 4286 + case READING_MODULE_COMPRESSED: 4286 4287 rc = selinux_kernel_load_from_file(file, SYSTEM__MODULE_LOAD); 4287 4288 break; 4288 4289 case READING_KEXEC_IMAGE: ··· 4312 4311 { 4313 4312 int rc = 0; 4314 4313 4315 - BUILD_BUG_ON_MSG(LOADING_MAX_ID > 7, 4314 + BUILD_BUG_ON_MSG(LOADING_MAX_ID > 8, 4316 4315 "New kernel_load_data_id introduced; update SELinux!"); 4317 4316 4318 4317 switch (id) {