Skip to content

Commit ba199dc

Browse files
bowerscd-corppcmoore
authored andcommitted
scripts: add boot policy generation program
Enables an IPE policy to be enforced from kernel start, enabling access control based on trust from kernel startup. This is accomplished by transforming an IPE policy indicated by CONFIG_IPE_BOOT_POLICY into a c-string literal that is parsed at kernel startup as an unsigned policy. Signed-off-by: Deven Bowers <[email protected]> Signed-off-by: Fan Wu <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent 31f8c86 commit ba199dc

File tree

10 files changed

+198
-0
lines changed

10 files changed

+198
-0
lines changed

scripts/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ targets += module.lds
5555
subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
5656
subdir-$(CONFIG_MODVERSIONS) += genksyms
5757
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
58+
subdir-$(CONFIG_SECURITY_IPE) += ipe
5859

5960
# Let clean descend into subdirs
6061
subdir- += basic dtc gdb kconfig mod

scripts/ipe/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
subdir-y := polgen

scripts/ipe/polgen/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
polgen

scripts/ipe/polgen/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
hostprogs-always-y := polgen
3+
HOST_EXTRACFLAGS += \
4+
-I$(srctree)/include \
5+
-I$(srctree)/include/uapi \

scripts/ipe/polgen/polgen.c

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4+
*/
5+
6+
#include <stdlib.h>
7+
#include <stddef.h>
8+
#include <stdio.h>
9+
#include <unistd.h>
10+
#include <errno.h>
11+
12+
static void usage(const char *const name)
13+
{
14+
printf("Usage: %s OutputFile (PolicyFile)\n", name);
15+
exit(EINVAL);
16+
}
17+
18+
static int policy_to_buffer(const char *pathname, char **buffer, size_t *size)
19+
{
20+
size_t fsize;
21+
size_t read;
22+
char *lbuf;
23+
int rc = 0;
24+
FILE *fd;
25+
26+
fd = fopen(pathname, "r");
27+
if (!fd) {
28+
rc = errno;
29+
goto out;
30+
}
31+
32+
fseek(fd, 0, SEEK_END);
33+
fsize = ftell(fd);
34+
rewind(fd);
35+
36+
lbuf = malloc(fsize);
37+
if (!lbuf) {
38+
rc = ENOMEM;
39+
goto out_close;
40+
}
41+
42+
read = fread((void *)lbuf, sizeof(*lbuf), fsize, fd);
43+
if (read != fsize) {
44+
rc = -1;
45+
goto out_free;
46+
}
47+
48+
*buffer = lbuf;
49+
*size = fsize;
50+
fclose(fd);
51+
52+
return rc;
53+
54+
out_free:
55+
free(lbuf);
56+
out_close:
57+
fclose(fd);
58+
out:
59+
return rc;
60+
}
61+
62+
static int write_boot_policy(const char *pathname, const char *buf, size_t size)
63+
{
64+
int rc = 0;
65+
FILE *fd;
66+
size_t i;
67+
68+
fd = fopen(pathname, "w");
69+
if (!fd) {
70+
rc = errno;
71+
goto err;
72+
}
73+
74+
fprintf(fd, "/* This file is automatically generated.");
75+
fprintf(fd, " Do not edit. */\n");
76+
fprintf(fd, "#include <linux/stddef.h>\n");
77+
fprintf(fd, "\nextern const char *const ipe_boot_policy;\n\n");
78+
fprintf(fd, "const char *const ipe_boot_policy =\n");
79+
80+
if (!buf || size == 0) {
81+
fprintf(fd, "\tNULL;\n");
82+
fclose(fd);
83+
return 0;
84+
}
85+
86+
fprintf(fd, "\t\"");
87+
88+
for (i = 0; i < size; ++i) {
89+
switch (buf[i]) {
90+
case '"':
91+
fprintf(fd, "\\\"");
92+
break;
93+
case '\'':
94+
fprintf(fd, "'");
95+
break;
96+
case '\n':
97+
fprintf(fd, "\\n\"\n\t\"");
98+
break;
99+
case '\\':
100+
fprintf(fd, "\\\\");
101+
break;
102+
case '\t':
103+
fprintf(fd, "\\t");
104+
break;
105+
case '\?':
106+
fprintf(fd, "\\?");
107+
break;
108+
default:
109+
fprintf(fd, "%c", buf[i]);
110+
}
111+
}
112+
fprintf(fd, "\";\n");
113+
fclose(fd);
114+
115+
return 0;
116+
117+
err:
118+
if (fd)
119+
fclose(fd);
120+
return rc;
121+
}
122+
123+
int main(int argc, const char *const argv[])
124+
{
125+
char *policy = NULL;
126+
size_t len = 0;
127+
int rc = 0;
128+
129+
if (argc < 2)
130+
usage(argv[0]);
131+
132+
if (argc > 2) {
133+
rc = policy_to_buffer(argv[2], &policy, &len);
134+
if (rc != 0)
135+
goto cleanup;
136+
}
137+
138+
rc = write_boot_policy(argv[1], policy, len);
139+
cleanup:
140+
if (policy)
141+
free(policy);
142+
if (rc != 0)
143+
perror("An error occurred during policy conversion: ");
144+
return rc;
145+
}

security/ipe/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
boot_policy.c

security/ipe/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ menuconfig SECURITY_IPE
2121
If unsure, answer N.
2222

2323
if SECURITY_IPE
24+
config IPE_BOOT_POLICY
25+
string "Integrity policy to apply on system startup"
26+
help
27+
This option specifies a filepath to an IPE policy that is compiled
28+
into the kernel. This policy will be enforced until a policy update
29+
is deployed via the $securityfs/ipe/policies/$policy_name/active
30+
interface.
31+
32+
If unsure, leave blank.
33+
2434
menu "IPE Trust Providers"
2535

2636
config IPE_PROP_DM_VERITY

security/ipe/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@
55
# Makefile for building the IPE module as part of the kernel tree.
66
#
77

8+
quiet_cmd_polgen = IPE_POL $(2)
9+
cmd_polgen = scripts/ipe/polgen/polgen security/ipe/boot_policy.c $(2)
10+
11+
targets += boot_policy.c
12+
13+
$(obj)/boot_policy.c: scripts/ipe/polgen/polgen $(CONFIG_IPE_BOOT_POLICY) FORCE
14+
$(call if_changed,polgen,$(CONFIG_IPE_BOOT_POLICY))
15+
816
obj-$(CONFIG_SECURITY_IPE) += \
17+
boot_policy.o \
918
digest.o \
1019
eval.o \
1120
hooks.o \
@@ -15,3 +24,5 @@ obj-$(CONFIG_SECURITY_IPE) += \
1524
policy_fs.o \
1625
policy_parser.o \
1726
audit.o \
27+
28+
clean-files := boot_policy.c \

security/ipe/fs.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ static const struct file_operations enforce_fops = {
190190
static int __init ipe_init_securityfs(void)
191191
{
192192
int rc = 0;
193+
struct ipe_policy *ap;
193194

194195
if (!ipe_enabled)
195196
return -EOPNOTSUPP;
@@ -220,6 +221,13 @@ static int __init ipe_init_securityfs(void)
220221
goto err;
221222
}
222223

224+
ap = rcu_access_pointer(ipe_active_policy);
225+
if (ap) {
226+
rc = ipe_new_policyfs_node(ap);
227+
if (rc)
228+
goto err;
229+
}
230+
223231
np = securityfs_create_file("new_policy", 0200, root, NULL, &np_fops);
224232
if (IS_ERR(np)) {
225233
rc = PTR_ERR(np);

security/ipe/ipe.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "hooks.h"
1010
#include "eval.h"
1111

12+
extern const char *const ipe_boot_policy;
1213
bool ipe_enabled;
1314

1415
static struct lsm_blob_sizes ipe_blobs __ro_after_init = {
@@ -74,9 +75,20 @@ static struct security_hook_list ipe_hooks[] __ro_after_init = {
7475
*/
7576
static int __init ipe_init(void)
7677
{
78+
struct ipe_policy *p = NULL;
79+
7780
security_add_hooks(ipe_hooks, ARRAY_SIZE(ipe_hooks), &ipe_lsmid);
7881
ipe_enabled = true;
7982

83+
if (ipe_boot_policy) {
84+
p = ipe_new_policy(ipe_boot_policy, strlen(ipe_boot_policy),
85+
NULL, 0);
86+
if (IS_ERR(p))
87+
return PTR_ERR(p);
88+
89+
rcu_assign_pointer(ipe_active_policy, p);
90+
}
91+
8092
return 0;
8193
}
8294

0 commit comments

Comments
 (0)