Skip to content

Commit 16c267a

Browse files
Mimi ZoharJames Morris
authored andcommitted
ima: based on policy require signed kexec kernel images
The original kexec_load syscall can not verify file signatures, nor can the kexec image be measured. Based on policy, deny the kexec_load syscall. Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com> Cc: Eric Biederman <ebiederm@xmission.com> Cc: Kees Cook <keescook@chromium.org> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: James Morris <james.morris@microsoft.com>
1 parent a210fd3 commit 16c267a

File tree

5 files changed

+43
-1
lines changed

5 files changed

+43
-1
lines changed

include/linux/ima.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LINUX_IMA_H
1212

1313
#include <linux/fs.h>
14+
#include <linux/security.h>
1415
#include <linux/kexec.h>
1516
struct linux_binprm;
1617

@@ -19,6 +20,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
1920
extern int ima_file_check(struct file *file, int mask, int opened);
2021
extern void ima_file_free(struct file *file);
2122
extern int ima_file_mmap(struct file *file, unsigned long prot);
23+
extern int ima_load_data(enum kernel_load_data_id id);
2224
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
2325
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
2426
enum kernel_read_file_id id);
@@ -49,6 +51,11 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
4951
return 0;
5052
}
5153

54+
static inline int ima_load_data(enum kernel_load_data_id id)
55+
{
56+
return 0;
57+
}
58+
5259
static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
5360
{
5461
return 0;

security/integrity/ima/ima.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ int ima_policy_show(struct seq_file *m, void *v);
232232
#define IMA_APPRAISE_MODULES 0x08
233233
#define IMA_APPRAISE_FIRMWARE 0x10
234234
#define IMA_APPRAISE_POLICY 0x20
235+
#define IMA_APPRAISE_KEXEC 0x40
235236

236237
#ifdef CONFIG_IMA_APPRAISE
237238
int ima_appraise_measurement(enum ima_hooks func,

security/integrity/ima/ima_main.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,33 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
496496
MAY_READ, func, 0);
497497
}
498498

499+
/**
500+
* ima_load_data - appraise decision based on policy
501+
* @id: kernel load data caller identifier
502+
*
503+
* Callers of this LSM hook can not measure, appraise, or audit the
504+
* data provided by userspace. Enforce policy rules requring a file
505+
* signature (eg. kexec'ed kernel image).
506+
*
507+
* For permission return 0, otherwise return -EACCES.
508+
*/
509+
int ima_load_data(enum kernel_load_data_id id)
510+
{
511+
if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
512+
return 0;
513+
514+
switch (id) {
515+
case LOADING_KEXEC_IMAGE:
516+
if (ima_appraise & IMA_APPRAISE_KEXEC) {
517+
pr_err("impossible to appraise a kernel image without a file descriptor; try using kexec_file_load syscall.\n");
518+
return -EACCES; /* INTEGRITY_UNKNOWN */
519+
}
520+
default:
521+
break;
522+
}
523+
return 0;
524+
}
525+
499526
static int __init init_ima(void)
500527
{
501528
int error;

security/integrity/ima/ima_policy.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ static int ima_appraise_flag(enum ima_hooks func)
448448
return IMA_APPRAISE_FIRMWARE;
449449
else if (func == POLICY_CHECK)
450450
return IMA_APPRAISE_POLICY;
451+
else if (func == KEXEC_KERNEL_CHECK)
452+
return IMA_APPRAISE_KEXEC;
451453
return 0;
452454
}
453455

security/security.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,12 @@ EXPORT_SYMBOL_GPL(security_kernel_post_read_file);
10581058

10591059
int security_kernel_load_data(enum kernel_load_data_id id)
10601060
{
1061-
return call_int_hook(kernel_load_data, 0, id);
1061+
int ret;
1062+
1063+
ret = call_int_hook(kernel_load_data, 0, id);
1064+
if (ret)
1065+
return ret;
1066+
return ima_load_data(id);
10621067
}
10631068

10641069
int security_task_fix_setuid(struct cred *new, const struct cred *old,

0 commit comments

Comments
 (0)