Skip to content

Commit 52443cb

Browse files
bowerscd-corppcmoore
authored andcommitted
ipe: add LSM hooks on execution and kernel read
IPE's initial goal is to control both execution and the loading of kernel modules based on the system's definition of trust. It accomplishes this by plugging into the security hooks for bprm_check_security, file_mprotect, mmap_file, kernel_load_data, and kernel_read_data. Signed-off-by: Deven Bowers <[email protected]> Signed-off-by: Fan Wu <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent 05a3516 commit 52443cb

File tree

6 files changed

+235
-0
lines changed

6 files changed

+235
-0
lines changed

security/ipe/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
obj-$(CONFIG_SECURITY_IPE) += \
99
eval.o \
10+
hooks.o \
1011
ipe.o \
1112
policy.o \
1213
policy_parser.o \

security/ipe/eval.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@
1616

1717
struct ipe_policy __rcu *ipe_active_policy;
1818

19+
/**
20+
* ipe_build_eval_ctx() - Build an ipe evaluation context.
21+
* @ctx: Supplies a pointer to the context to be populated.
22+
* @file: Supplies a pointer to the file to associated with the evaluation.
23+
* @op: Supplies the IPE policy operation associated with the evaluation.
24+
*/
25+
void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
26+
const struct file *file,
27+
enum ipe_op_type op)
28+
{
29+
ctx->file = file;
30+
ctx->op = op;
31+
}
32+
1933
/**
2034
* evaluate_property() - Analyze @ctx against a rule property.
2135
* @ctx: Supplies a pointer to the context to be evaluated.

security/ipe/eval.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
#include "policy.h"
1313

14+
#define IPE_EVAL_CTX_INIT ((struct ipe_eval_ctx){ 0 })
15+
1416
extern struct ipe_policy __rcu *ipe_active_policy;
1517

1618
struct ipe_eval_ctx {
@@ -19,6 +21,9 @@ struct ipe_eval_ctx {
1921
const struct file *file;
2022
};
2123

24+
void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
25+
const struct file *file,
26+
enum ipe_op_type op);
2227
int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx);
2328

2429
#endif /* _IPE_EVAL_H */

security/ipe/hooks.c

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4+
*/
5+
6+
#include <linux/fs.h>
7+
#include <linux/types.h>
8+
#include <linux/binfmts.h>
9+
#include <linux/mman.h>
10+
11+
#include "ipe.h"
12+
#include "hooks.h"
13+
#include "eval.h"
14+
15+
/**
16+
* ipe_bprm_check_security() - ipe security hook function for bprm check.
17+
* @bprm: Supplies a pointer to a linux_binprm structure to source the file
18+
* being evaluated.
19+
*
20+
* This LSM hook is called when a binary is loaded through the exec
21+
* family of system calls.
22+
*
23+
* Return:
24+
* * %0 - Success
25+
* * %-EACCES - Did not pass IPE policy
26+
*/
27+
int ipe_bprm_check_security(struct linux_binprm *bprm)
28+
{
29+
struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
30+
31+
ipe_build_eval_ctx(&ctx, bprm->file, IPE_OP_EXEC);
32+
return ipe_evaluate_event(&ctx);
33+
}
34+
35+
/**
36+
* ipe_mmap_file() - ipe security hook function for mmap check.
37+
* @f: File being mmap'd. Can be NULL in the case of anonymous memory.
38+
* @reqprot: The requested protection on the mmap, passed from usermode.
39+
* @prot: The effective protection on the mmap, resolved from reqprot and
40+
* system configuration.
41+
* @flags: Unused.
42+
*
43+
* This hook is called when a file is loaded through the mmap
44+
* family of system calls.
45+
*
46+
* Return:
47+
* * %0 - Success
48+
* * %-EACCES - Did not pass IPE policy
49+
*/
50+
int ipe_mmap_file(struct file *f, unsigned long reqprot __always_unused,
51+
unsigned long prot, unsigned long flags)
52+
{
53+
struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
54+
55+
if (prot & PROT_EXEC) {
56+
ipe_build_eval_ctx(&ctx, f, IPE_OP_EXEC);
57+
return ipe_evaluate_event(&ctx);
58+
}
59+
60+
return 0;
61+
}
62+
63+
/**
64+
* ipe_file_mprotect() - ipe security hook function for mprotect check.
65+
* @vma: Existing virtual memory area created by mmap or similar.
66+
* @reqprot: The requested protection on the mmap, passed from usermode.
67+
* @prot: The effective protection on the mmap, resolved from reqprot and
68+
* system configuration.
69+
*
70+
* This LSM hook is called when a mmap'd region of memory is changing
71+
* its protections via mprotect.
72+
*
73+
* Return:
74+
* * %0 - Success
75+
* * %-EACCES - Did not pass IPE policy
76+
*/
77+
int ipe_file_mprotect(struct vm_area_struct *vma,
78+
unsigned long reqprot __always_unused,
79+
unsigned long prot)
80+
{
81+
struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
82+
83+
/* Already Executable */
84+
if (vma->vm_flags & VM_EXEC)
85+
return 0;
86+
87+
if (prot & PROT_EXEC) {
88+
ipe_build_eval_ctx(&ctx, vma->vm_file, IPE_OP_EXEC);
89+
return ipe_evaluate_event(&ctx);
90+
}
91+
92+
return 0;
93+
}
94+
95+
/**
96+
* ipe_kernel_read_file() - ipe security hook function for kernel read.
97+
* @file: Supplies a pointer to the file structure being read in from disk.
98+
* @id: Supplies the enumeration identifying the purpose of the read.
99+
* @contents: Unused.
100+
*
101+
* This LSM hook is called when a file is read from disk in the kernel.
102+
*
103+
* Return:
104+
* * %0 - Success
105+
* * %-EACCES - Did not pass IPE policy
106+
*/
107+
int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
108+
bool contents)
109+
{
110+
struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
111+
enum ipe_op_type op;
112+
113+
switch (id) {
114+
case READING_FIRMWARE:
115+
op = IPE_OP_FIRMWARE;
116+
break;
117+
case READING_MODULE:
118+
op = IPE_OP_KERNEL_MODULE;
119+
break;
120+
case READING_KEXEC_INITRAMFS:
121+
op = IPE_OP_KEXEC_INITRAMFS;
122+
break;
123+
case READING_KEXEC_IMAGE:
124+
op = IPE_OP_KEXEC_IMAGE;
125+
break;
126+
case READING_POLICY:
127+
op = IPE_OP_POLICY;
128+
break;
129+
case READING_X509_CERTIFICATE:
130+
op = IPE_OP_X509;
131+
break;
132+
default:
133+
op = IPE_OP_INVALID;
134+
WARN(1, "no rule setup for kernel_read_file enum %d", id);
135+
}
136+
137+
ipe_build_eval_ctx(&ctx, file, op);
138+
return ipe_evaluate_event(&ctx);
139+
}
140+
141+
/**
142+
* ipe_kernel_load_data() - ipe security hook function for kernel load data.
143+
* @id: Supplies the enumeration identifying the purpose of the load.
144+
* @contents: Unused.
145+
*
146+
* This LSM hook is called when a data buffer provided by userspace is loading
147+
* into the kernel.
148+
*
149+
* Return:
150+
* * %0 - Success
151+
* * %-EACCES - Did not pass IPE policy
152+
*/
153+
int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents)
154+
{
155+
struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
156+
enum ipe_op_type op;
157+
158+
switch (id) {
159+
case LOADING_FIRMWARE:
160+
op = IPE_OP_FIRMWARE;
161+
break;
162+
case LOADING_MODULE:
163+
op = IPE_OP_KERNEL_MODULE;
164+
break;
165+
case LOADING_KEXEC_INITRAMFS:
166+
op = IPE_OP_KEXEC_INITRAMFS;
167+
break;
168+
case LOADING_KEXEC_IMAGE:
169+
op = IPE_OP_KEXEC_IMAGE;
170+
break;
171+
case LOADING_POLICY:
172+
op = IPE_OP_POLICY;
173+
break;
174+
case LOADING_X509_CERTIFICATE:
175+
op = IPE_OP_X509;
176+
break;
177+
default:
178+
op = IPE_OP_INVALID;
179+
WARN(1, "no rule setup for kernel_load_data enum %d", id);
180+
}
181+
182+
ipe_build_eval_ctx(&ctx, NULL, op);
183+
return ipe_evaluate_event(&ctx);
184+
}

security/ipe/hooks.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4+
*/
5+
#ifndef _IPE_HOOKS_H
6+
#define _IPE_HOOKS_H
7+
8+
#include <linux/fs.h>
9+
#include <linux/binfmts.h>
10+
#include <linux/security.h>
11+
12+
int ipe_bprm_check_security(struct linux_binprm *bprm);
13+
14+
int ipe_mmap_file(struct file *f, unsigned long reqprot, unsigned long prot,
15+
unsigned long flags);
16+
17+
int ipe_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
18+
unsigned long prot);
19+
20+
int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
21+
bool contents);
22+
23+
int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents);
24+
25+
#endif /* _IPE_HOOKS_H */

security/ipe/ipe.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <uapi/linux/lsm.h>
66

77
#include "ipe.h"
8+
#include "hooks.h"
89

910
static struct lsm_blob_sizes ipe_blobs __ro_after_init = {
1011
};
@@ -15,6 +16,11 @@ static const struct lsm_id ipe_lsmid = {
1516
};
1617

1718
static struct security_hook_list ipe_hooks[] __ro_after_init = {
19+
LSM_HOOK_INIT(bprm_check_security, ipe_bprm_check_security),
20+
LSM_HOOK_INIT(mmap_file, ipe_mmap_file),
21+
LSM_HOOK_INIT(file_mprotect, ipe_file_mprotect),
22+
LSM_HOOK_INIT(kernel_read_file, ipe_kernel_read_file),
23+
LSM_HOOK_INIT(kernel_load_data, ipe_kernel_load_data),
1824
};
1925

2026
/**

0 commit comments

Comments
 (0)