diff options
author | Prakhar Srivastava <prsriva02@gmail.com> | 2019-06-24 02:23:29 -0400 |
---|---|---|
committer | Mimi Zohar <zohar@linux.ibm.com> | 2019-06-24 08:29:57 -0400 |
commit | b0935123a18360d19f1dcc779ea33841cdc304cc (patch) | |
tree | f7f069f94312da4302ad6b1b793d4f6c90eb5bc0 | |
parent | 19453ce0bcfbdf7332a104eebf5d835977af7284 (diff) |
IMA: Define a new hook to measure the kexec boot command line arguments
Currently during soft reboot(kexec_file_load) boot command line
arguments are not measured. Define hooks needed to measure kexec
command line arguments during soft reboot(kexec_file_load).
- A new ima hook ima_kexec_cmdline is defined to be called by the
kexec code.
- A new function process_buffer_measurement is defined to measure
the buffer hash into the IMA measurement list.
- A new func policy KEXEC_CMDLINE is defined to control the
measurement.
Signed-off-by: Prakhar Srivastava <prsriva02@gmail.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
-rw-r--r-- | Documentation/ABI/testing/ima_policy | 1 | ||||
-rw-r--r-- | include/linux/ima.h | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 1 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 1 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 72 | ||||
-rw-r--r-- | security/integrity/ima/ima_policy.c | 7 |
6 files changed, 84 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index b383c1763610..fc376a323908 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy | |||
@@ -28,6 +28,7 @@ Description: | |||
28 | base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] | 28 | base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] |
29 | [FIRMWARE_CHECK] | 29 | [FIRMWARE_CHECK] |
30 | [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] | 30 | [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] |
31 | [KEXEC_CMDLINE] | ||
31 | mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] | 32 | mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] |
32 | [[^]MAY_EXEC] | 33 | [[^]MAY_EXEC] |
33 | fsmagic:= hex value | 34 | fsmagic:= hex value |
diff --git a/include/linux/ima.h b/include/linux/ima.h index fd9f7cf4cdf5..b42f5a006042 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h | |||
@@ -26,6 +26,7 @@ extern int ima_read_file(struct file *file, enum kernel_read_file_id id); | |||
26 | extern int ima_post_read_file(struct file *file, void *buf, loff_t size, | 26 | extern int ima_post_read_file(struct file *file, void *buf, loff_t size, |
27 | enum kernel_read_file_id id); | 27 | enum kernel_read_file_id id); |
28 | extern void ima_post_path_mknod(struct dentry *dentry); | 28 | extern void ima_post_path_mknod(struct dentry *dentry); |
29 | extern void ima_kexec_cmdline(const void *buf, int size); | ||
29 | 30 | ||
30 | #ifdef CONFIG_IMA_KEXEC | 31 | #ifdef CONFIG_IMA_KEXEC |
31 | extern void ima_add_kexec_buffer(struct kimage *image); | 32 | extern void ima_add_kexec_buffer(struct kimage *image); |
@@ -92,6 +93,7 @@ static inline void ima_post_path_mknod(struct dentry *dentry) | |||
92 | return; | 93 | return; |
93 | } | 94 | } |
94 | 95 | ||
96 | static inline void ima_kexec_cmdline(const void *buf, int size) {} | ||
95 | #endif /* CONFIG_IMA */ | 97 | #endif /* CONFIG_IMA */ |
96 | 98 | ||
97 | #ifndef CONFIG_IMA_KEXEC | 99 | #ifndef CONFIG_IMA_KEXEC |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index e7b9ea7732d9..bdca641f9e51 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -190,6 +190,7 @@ static inline unsigned long ima_hash_key(u8 *digest) | |||
190 | hook(KEXEC_KERNEL_CHECK) \ | 190 | hook(KEXEC_KERNEL_CHECK) \ |
191 | hook(KEXEC_INITRAMFS_CHECK) \ | 191 | hook(KEXEC_INITRAMFS_CHECK) \ |
192 | hook(POLICY_CHECK) \ | 192 | hook(POLICY_CHECK) \ |
193 | hook(KEXEC_CMDLINE) \ | ||
193 | hook(MAX_CHECK) | 194 | hook(MAX_CHECK) |
194 | #define __ima_hook_enumify(ENUM) ENUM, | 195 | #define __ima_hook_enumify(ENUM) ENUM, |
195 | 196 | ||
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index c0cf4bcfc82f..d426d4d1fe04 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -178,6 +178,7 @@ err_out: | |||
178 | * subj=, obj=, type=, func=, mask=, fsmagic= | 178 | * subj=, obj=, type=, func=, mask=, fsmagic= |
179 | * subj,obj, and type: are LSM specific. | 179 | * subj,obj, and type: are LSM specific. |
180 | * func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK | 180 | * func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK |
181 | * | KEXEC_CMDLINE | ||
181 | * mask: contains the permission mask | 182 | * mask: contains the permission mask |
182 | * fsmagic: hex value | 183 | * fsmagic: hex value |
183 | * | 184 | * |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index a7e7e2d7224c..2507bee1b762 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -609,6 +609,78 @@ int ima_load_data(enum kernel_load_data_id id) | |||
609 | return 0; | 609 | return 0; |
610 | } | 610 | } |
611 | 611 | ||
612 | /* | ||
613 | * process_buffer_measurement - Measure the buffer to ima log. | ||
614 | * @buf: pointer to the buffer that needs to be added to the log. | ||
615 | * @size: size of buffer(in bytes). | ||
616 | * @eventname: event name to be used for the buffer entry. | ||
617 | * @cred: a pointer to a credentials structure for user validation. | ||
618 | * @secid: the secid of the task to be validated. | ||
619 | * | ||
620 | * Based on policy, the buffer is measured into the ima log. | ||
621 | */ | ||
622 | static void process_buffer_measurement(const void *buf, int size, | ||
623 | const char *eventname, | ||
624 | const struct cred *cred, u32 secid) | ||
625 | { | ||
626 | int ret = 0; | ||
627 | struct ima_template_entry *entry = NULL; | ||
628 | struct integrity_iint_cache iint = {}; | ||
629 | struct ima_event_data event_data = {.iint = &iint, | ||
630 | .filename = eventname}; | ||
631 | struct ima_template_desc *template_desc = NULL; | ||
632 | struct { | ||
633 | struct ima_digest_data hdr; | ||
634 | char digest[IMA_MAX_DIGEST_SIZE]; | ||
635 | } hash = {}; | ||
636 | int violation = 0; | ||
637 | int pcr = CONFIG_IMA_MEASURE_PCR_IDX; | ||
638 | int action = 0; | ||
639 | |||
640 | action = ima_get_action(NULL, cred, secid, 0, KEXEC_CMDLINE, &pcr, | ||
641 | &template_desc); | ||
642 | if (!(action & IMA_MEASURE)) | ||
643 | return; | ||
644 | |||
645 | iint.ima_hash = &hash.hdr; | ||
646 | iint.ima_hash->algo = ima_hash_algo; | ||
647 | iint.ima_hash->length = hash_digest_size[ima_hash_algo]; | ||
648 | |||
649 | ret = ima_calc_buffer_hash(buf, size, iint.ima_hash); | ||
650 | if (ret < 0) | ||
651 | goto out; | ||
652 | |||
653 | ret = ima_alloc_init_template(&event_data, &entry, template_desc); | ||
654 | if (ret < 0) | ||
655 | goto out; | ||
656 | |||
657 | ret = ima_store_template(entry, violation, NULL, buf, pcr); | ||
658 | |||
659 | if (ret < 0) | ||
660 | ima_free_template_entry(entry); | ||
661 | |||
662 | out: | ||
663 | return; | ||
664 | } | ||
665 | |||
666 | /** | ||
667 | * ima_kexec_cmdline - measure kexec cmdline boot args | ||
668 | * @buf: pointer to buffer | ||
669 | * @size: size of buffer | ||
670 | * | ||
671 | * Buffers can only be measured, not appraised. | ||
672 | */ | ||
673 | void ima_kexec_cmdline(const void *buf, int size) | ||
674 | { | ||
675 | u32 secid; | ||
676 | |||
677 | if (buf && size != 0) { | ||
678 | security_task_getsecid(current, &secid); | ||
679 | process_buffer_measurement(buf, size, "kexec-cmdline", | ||
680 | current_cred(), secid); | ||
681 | } | ||
682 | } | ||
683 | |||
612 | static int __init init_ima(void) | 684 | static int __init init_ima(void) |
613 | { | 685 | { |
614 | int error; | 686 | int error; |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 98c289559079..a3058b03a955 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
@@ -374,6 +374,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, | |||
374 | { | 374 | { |
375 | int i; | 375 | int i; |
376 | 376 | ||
377 | if (func == KEXEC_CMDLINE) { | ||
378 | if ((rule->flags & IMA_FUNC) && (rule->func == func)) | ||
379 | return true; | ||
380 | return false; | ||
381 | } | ||
377 | if ((rule->flags & IMA_FUNC) && | 382 | if ((rule->flags & IMA_FUNC) && |
378 | (rule->func != func && func != POST_SETATTR)) | 383 | (rule->func != func && func != POST_SETATTR)) |
379 | return false; | 384 | return false; |
@@ -956,6 +961,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) | |||
956 | entry->func = KEXEC_INITRAMFS_CHECK; | 961 | entry->func = KEXEC_INITRAMFS_CHECK; |
957 | else if (strcmp(args[0].from, "POLICY_CHECK") == 0) | 962 | else if (strcmp(args[0].from, "POLICY_CHECK") == 0) |
958 | entry->func = POLICY_CHECK; | 963 | entry->func = POLICY_CHECK; |
964 | else if (strcmp(args[0].from, "KEXEC_CMDLINE") == 0) | ||
965 | entry->func = KEXEC_CMDLINE; | ||
959 | else | 966 | else |
960 | result = -EINVAL; | 967 | result = -EINVAL; |
961 | if (!result) | 968 | if (!result) |