Skip to content

Commit

Permalink
scripts: add boot policy generation program
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
bowerscd-corp authored and pcmoore committed Aug 20, 2024
1 parent 31f8c86 commit ba199dc
Show file tree
Hide file tree
Showing 10 changed files with 198 additions and 0 deletions.
1 change: 1 addition & 0 deletions scripts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ targets += module.lds
subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
subdir-$(CONFIG_MODVERSIONS) += genksyms
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
subdir-$(CONFIG_SECURITY_IPE) += ipe

# Let clean descend into subdirs
subdir- += basic dtc gdb kconfig mod
2 changes: 2 additions & 0 deletions scripts/ipe/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
subdir-y := polgen
2 changes: 2 additions & 0 deletions scripts/ipe/polgen/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
polgen
5 changes: 5 additions & 0 deletions scripts/ipe/polgen/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
hostprogs-always-y := polgen
HOST_EXTRACFLAGS += \
-I$(srctree)/include \
-I$(srctree)/include/uapi \
145 changes: 145 additions & 0 deletions scripts/ipe/polgen/polgen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
*/

#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

static void usage(const char *const name)
{
printf("Usage: %s OutputFile (PolicyFile)\n", name);
exit(EINVAL);
}

static int policy_to_buffer(const char *pathname, char **buffer, size_t *size)
{
size_t fsize;
size_t read;
char *lbuf;
int rc = 0;
FILE *fd;

fd = fopen(pathname, "r");
if (!fd) {
rc = errno;
goto out;
}

fseek(fd, 0, SEEK_END);
fsize = ftell(fd);
rewind(fd);

lbuf = malloc(fsize);
if (!lbuf) {
rc = ENOMEM;
goto out_close;
}

read = fread((void *)lbuf, sizeof(*lbuf), fsize, fd);
if (read != fsize) {
rc = -1;
goto out_free;
}

*buffer = lbuf;
*size = fsize;
fclose(fd);

return rc;

out_free:
free(lbuf);
out_close:
fclose(fd);
out:
return rc;
}

static int write_boot_policy(const char *pathname, const char *buf, size_t size)
{
int rc = 0;
FILE *fd;
size_t i;

fd = fopen(pathname, "w");
if (!fd) {
rc = errno;
goto err;
}

fprintf(fd, "/* This file is automatically generated.");
fprintf(fd, " Do not edit. */\n");
fprintf(fd, "#include <linux/stddef.h>\n");
fprintf(fd, "\nextern const char *const ipe_boot_policy;\n\n");
fprintf(fd, "const char *const ipe_boot_policy =\n");

if (!buf || size == 0) {
fprintf(fd, "\tNULL;\n");
fclose(fd);
return 0;
}

fprintf(fd, "\t\"");

for (i = 0; i < size; ++i) {
switch (buf[i]) {
case '"':
fprintf(fd, "\\\"");
break;
case '\'':
fprintf(fd, "'");
break;
case '\n':
fprintf(fd, "\\n\"\n\t\"");
break;
case '\\':
fprintf(fd, "\\\\");
break;
case '\t':
fprintf(fd, "\\t");
break;
case '\?':
fprintf(fd, "\\?");
break;
default:
fprintf(fd, "%c", buf[i]);
}
}
fprintf(fd, "\";\n");
fclose(fd);

return 0;

err:
if (fd)
fclose(fd);
return rc;
}

int main(int argc, const char *const argv[])
{
char *policy = NULL;
size_t len = 0;
int rc = 0;

if (argc < 2)
usage(argv[0]);

if (argc > 2) {
rc = policy_to_buffer(argv[2], &policy, &len);
if (rc != 0)
goto cleanup;
}

rc = write_boot_policy(argv[1], policy, len);
cleanup:
if (policy)
free(policy);
if (rc != 0)
perror("An error occurred during policy conversion: ");
return rc;
}
2 changes: 2 additions & 0 deletions security/ipe/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
boot_policy.c
10 changes: 10 additions & 0 deletions security/ipe/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ menuconfig SECURITY_IPE
If unsure, answer N.

if SECURITY_IPE
config IPE_BOOT_POLICY
string "Integrity policy to apply on system startup"
help
This option specifies a filepath to an IPE policy that is compiled
into the kernel. This policy will be enforced until a policy update
is deployed via the $securityfs/ipe/policies/$policy_name/active
interface.

If unsure, leave blank.

menu "IPE Trust Providers"

config IPE_PROP_DM_VERITY
Expand Down
11 changes: 11 additions & 0 deletions security/ipe/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@
# Makefile for building the IPE module as part of the kernel tree.
#

quiet_cmd_polgen = IPE_POL $(2)
cmd_polgen = scripts/ipe/polgen/polgen security/ipe/boot_policy.c $(2)

targets += boot_policy.c

$(obj)/boot_policy.c: scripts/ipe/polgen/polgen $(CONFIG_IPE_BOOT_POLICY) FORCE
$(call if_changed,polgen,$(CONFIG_IPE_BOOT_POLICY))

obj-$(CONFIG_SECURITY_IPE) += \
boot_policy.o \
digest.o \
eval.o \
hooks.o \
Expand All @@ -15,3 +24,5 @@ obj-$(CONFIG_SECURITY_IPE) += \
policy_fs.o \
policy_parser.o \
audit.o \

clean-files := boot_policy.c \
8 changes: 8 additions & 0 deletions security/ipe/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ static const struct file_operations enforce_fops = {
static int __init ipe_init_securityfs(void)
{
int rc = 0;
struct ipe_policy *ap;

if (!ipe_enabled)
return -EOPNOTSUPP;
Expand Down Expand Up @@ -220,6 +221,13 @@ static int __init ipe_init_securityfs(void)
goto err;
}

ap = rcu_access_pointer(ipe_active_policy);
if (ap) {
rc = ipe_new_policyfs_node(ap);
if (rc)
goto err;
}

np = securityfs_create_file("new_policy", 0200, root, NULL, &np_fops);
if (IS_ERR(np)) {
rc = PTR_ERR(np);
Expand Down
12 changes: 12 additions & 0 deletions security/ipe/ipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "hooks.h"
#include "eval.h"

extern const char *const ipe_boot_policy;
bool ipe_enabled;

static struct lsm_blob_sizes ipe_blobs __ro_after_init = {
Expand Down Expand Up @@ -74,9 +75,20 @@ static struct security_hook_list ipe_hooks[] __ro_after_init = {
*/
static int __init ipe_init(void)
{
struct ipe_policy *p = NULL;

security_add_hooks(ipe_hooks, ARRAY_SIZE(ipe_hooks), &ipe_lsmid);
ipe_enabled = true;

if (ipe_boot_policy) {
p = ipe_new_policy(ipe_boot_policy, strlen(ipe_boot_policy),
NULL, 0);
if (IS_ERR(p))
return PTR_ERR(p);

rcu_assign_pointer(ipe_active_policy, p);
}

return 0;
}

Expand Down

0 comments on commit ba199dc

Please sign in to comment.