From 8df8b2d3e51d1b816201d8a1fe8bc29fe192e562 Mon Sep 17 00:00:00 2001 From: "Simon J. Gerraty" Date: Tue, 26 Feb 2019 06:22:10 +0000 Subject: [PATCH] Enable veriexec for loader This relies on libbearssl and libsecureboot to verify files read by loader in a maner equivalent to how mac_veriexec Note: disabled by default. Use is initially expected to be by embeded vendors Reviewed by: emaste, imp Sponsored by: Juniper Networks Differential Revision: D16336 --- stand/common/boot.c | 4 ++++ stand/common/bootstrap.h | 7 +++++++ stand/common/interp_forth.c | 7 +++++++ stand/common/interp_simple.c | 8 ++++++++ stand/common/load_elf.c | 6 ++++++ stand/common/load_elf_obj.c | 7 +++++++ stand/common/module.c | 26 +++++++++++++++++++++++++- stand/ficl/Makefile.depend | 4 +--- stand/ficl/ficl.h | 4 ++++ stand/ficl/fileaccess.c | 19 +++++++++++++------ stand/ficl32/Makefile.depend | 4 +--- stand/i386/loader/Makefile.depend | 15 ++++++--------- stand/liblua/Makefile | 3 +++ stand/liblua/lstd.c | 15 +++++++++++++++ stand/libsa/Makefile | 5 +++++ stand/libsa/Makefile.depend | 4 ---- stand/libsa32/Makefile.depend | 5 +---- stand/loader.mk | 4 ++++ 18 files changed, 117 insertions(+), 30 deletions(-) diff --git a/stand/common/boot.c b/stand/common/boot.c index f965dedb3bcf..d3fc8155e09b 100644 --- a/stand/common/boot.c +++ b/stand/common/boot.c @@ -106,6 +106,10 @@ command_boot(int argc, char *argv[]) if (archsw.arch_autoload() != 0) return(CMD_ERROR); +#ifdef LOADER_VERIEXEC + verify_pcr_export(); /* for measured boot */ +#endif + /* Call the exec handler from the loader matching the kernel */ file_formats[fp->f_loader]->l_exec(fp); return(CMD_ERROR); diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h index 47e6c3d056a2..3e723765104e 100644 --- a/stand/common/bootstrap.h +++ b/stand/common/bootstrap.h @@ -330,6 +330,9 @@ struct arch_switch /* Probe ZFS pool(s), if needed. */ void (*arch_zfs_probe)(void); + /* Return the hypervisor name/type or NULL if not virtualized. */ + const char *(*arch_hypervisor)(void); + /* For kexec-type loaders, get ksegment structure */ void (*arch_kexec_kseg_get)(int *nseg, void **kseg); }; @@ -346,4 +349,8 @@ time_t time(time_t *tloc); #define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") #endif +#ifdef LOADER_VERIEXEC +#include +#endif + #endif /* !_BOOTSTRAP_H_ */ diff --git a/stand/common/interp_forth.c b/stand/common/interp_forth.c index 19d66cdf3f4d..6304fe5057de 100644 --- a/stand/common/interp_forth.c +++ b/stand/common/interp_forth.c @@ -379,6 +379,13 @@ interp_include(const char *filename) return(CMD_ERROR); } +#ifdef LOADER_VERIEXEC + if (verify_file(fd, filename, 0, VE_GUESS) < 0) { + close(fd); + sprintf(command_errbuf,"can't verify '%s'", filename); + return(CMD_ERROR); + } +#endif /* * Read the script into memory. */ diff --git a/stand/common/interp_simple.c b/stand/common/interp_simple.c index 439f63fa966e..4c060236bbb6 100644 --- a/stand/common/interp_simple.c +++ b/stand/common/interp_simple.c @@ -96,6 +96,14 @@ interp_include(const char *filename) return(CMD_ERROR); } +#ifdef LOADER_VERIEXEC + if (verify_file(fd, filename, 0, VE_GUESS) < 0) { + close(fd); + sprintf(command_errbuf,"can't verify '%s'", filename); + return(CMD_ERROR); + } +#endif + /* * Read the script into memory. */ diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c index 695eec68a011..2356f24bd91b 100644 --- a/stand/common/load_elf.c +++ b/stand/common/load_elf.c @@ -245,6 +245,12 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef) goto error; } +#ifdef LOADER_VERIEXEC + if (verify_file(ef->fd, filename, bytes_read, VE_MUST) < 0) { + err = EAUTH; + goto error; + } +#endif return (0); error: diff --git a/stand/common/load_elf_obj.c b/stand/common/load_elf_obj.c index 3ff6e5f63b28..ae45ce7366b7 100644 --- a/stand/common/load_elf_obj.c +++ b/stand/common/load_elf_obj.c @@ -129,6 +129,13 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest, goto oerr; } +#ifdef LOADER_VERIEXEC + if (verify_file(ef.fd, filename, bytes_read, VE_MUST) < 0) { + err = EAUTH; + goto oerr; + } +#endif + kfp = file_findfile(NULL, __elfN(obj_kerneltype)); if (kfp == NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) diff --git a/stand/common/module.c b/stand/common/module.c index d651ad10bc86..1c1f2c286103 100644 --- a/stand/common/module.c +++ b/stand/common/module.c @@ -104,6 +104,8 @@ command_load(int argc, char *argv[]) { struct preloaded_file *fp; char *typestr; + char *prefix; + char *skip; int dofile, dokld, ch, error; dokld = dofile = 0; @@ -114,11 +116,18 @@ command_load(int argc, char *argv[]) command_errmsg = "no filename specified"; return (CMD_CRIT); } - while ((ch = getopt(argc, argv, "kt:")) != -1) { + prefix = skip = NULL; + while ((ch = getopt(argc, argv, "kp:s:t:")) != -1) { switch(ch) { case 'k': dokld = 1; break; + case 'p': + prefix = optarg; + break; + case 's': + skip = optarg; + break; case 't': typestr = optarg; dofile = 1; @@ -141,6 +150,12 @@ command_load(int argc, char *argv[]) return (CMD_CRIT); } +#ifdef LOADER_VERIEXEC + if (strncmp(typestr, "manifest", 8) == 0) { + return (load_manifest(argv[1], prefix, skip, NULL)); + } +#endif + fp = file_findfile(argv[1], typestr); if (fp) { snprintf(command_errbuf, sizeof(command_errbuf), @@ -435,6 +450,15 @@ file_loadraw(const char *fname, char *type, int insert) return(NULL); } +#ifdef LOADER_VERIEXEC + if (verify_file(fd, name, 0, VE_MUST) < 0) { + sprintf(command_errbuf, "can't verify '%s'", name); + free(name); + close(fd); + return(NULL); + } +#endif + if (archsw.arch_loadaddr != NULL) loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); diff --git a/stand/ficl/Makefile.depend b/stand/ficl/Makefile.depend index c210061155d2..73bc18c8c0fc 100644 --- a/stand/ficl/Makefile.depend +++ b/stand/ficl/Makefile.depend @@ -2,9 +2,7 @@ # Autogenerated - do NOT edit! DIRDEPS = \ - include \ - include/xlocale \ - lib/msun \ + stand/libsa \ .include diff --git a/stand/ficl/ficl.h b/stand/ficl/ficl.h index 8829ccea9668..a6f8f03c5732 100644 --- a/stand/ficl/ficl.h +++ b/stand/ficl/ficl.h @@ -1157,6 +1157,10 @@ typedef void ficlCompileFcn(FICL_SYSTEM *); DATA_SET(Xficl_compile_set, func) SET_DECLARE(Xficl_compile_set, ficlCompileFcn); +#ifdef LOADER_VERIEXEC +#include +#endif + #ifdef __cplusplus } #endif diff --git a/stand/ficl/fileaccess.c b/stand/ficl/fileaccess.c index 2b981c870975..b5e993b02dc2 100644 --- a/stand/ficl/fileaccess.c +++ b/stand/ficl/fileaccess.c @@ -67,14 +67,21 @@ static void ficlFopen(FICL_VM *pVM, char *writeMode) /* ( c-addr u fam -- fileid if (f == NULL) stackPushPtr(pVM->pStack, NULL); else +#ifdef LOADER_VERIEXEC + if (*mode == 'r' && + verify_file(fileno(f), filename, 0, VE_GUESS) < 0) { + fclose(f); + stackPushPtr(pVM->pStack, NULL); + } else +#endif { - ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE)); - strcpy(ff->filename, filename); - ff->f = f; - stackPushPtr(pVM->pStack, ff); + ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE)); + strcpy(ff->filename, filename); + ff->f = f; + stackPushPtr(pVM->pStack, ff); - fseek(f, 0, SEEK_SET); - } + fseek(f, 0, SEEK_SET); + } pushIor(pVM, f != NULL); } diff --git a/stand/ficl32/Makefile.depend b/stand/ficl32/Makefile.depend index c210061155d2..73bc18c8c0fc 100644 --- a/stand/ficl32/Makefile.depend +++ b/stand/ficl32/Makefile.depend @@ -2,9 +2,7 @@ # Autogenerated - do NOT edit! DIRDEPS = \ - include \ - include/xlocale \ - lib/msun \ + stand/libsa \ .include diff --git a/stand/i386/loader/Makefile.depend b/stand/i386/loader/Makefile.depend index 05739faa951d..8807f64e88d6 100644 --- a/stand/i386/loader/Makefile.depend +++ b/stand/i386/loader/Makefile.depend @@ -2,15 +2,12 @@ # Autogenerated - do NOT edit! DIRDEPS = \ - include \ - include/xlocale \ - stand/ficl32 \ - stand/geli \ - stand/i386/btx/btx \ - stand/i386/btx/btxldr \ - stand/i386/btx/lib \ - stand/i386/libi386 \ - stand/libsa32 \ + stand/${MACHINE_CPUARCH}/btx/btx \ + stand/${MACHINE_CPUARCH}/btx/btxldr \ + stand/${MACHINE_CPUARCH}/btx/lib \ + stand/${MACHINE_CPUARCH}/libi386 \ + stand/ficl \ + stand/libsa \ .include diff --git a/stand/liblua/Makefile b/stand/liblua/Makefile index ed1b850d577f..edbbf60b2d25 100644 --- a/stand/liblua/Makefile +++ b/stand/liblua/Makefile @@ -35,5 +35,8 @@ CFLAGS+= -I${BOOTSRC}/include -I${LIBLUASRC} -I${LUASRC} -I${LDRSRC} .if ${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 0 CFLAGS+= -fPIC .endif +.if ${MK_LOADER_VERIEXEC} == "yes" +CFLAGS+= -I${SRCTOP}/lib/libsecureboot/h -DLOADER_VERIEXEC +.endif .include diff --git a/stand/liblua/lstd.c b/stand/liblua/lstd.c index c71232ee1024..8efdaf7256be 100644 --- a/stand/liblua/lstd.c +++ b/stand/liblua/lstd.c @@ -31,6 +31,10 @@ __FBSDID("$FreeBSD$"); #include "lstd.h" #include "math.h" +#ifdef LOADER_VERIEXEC +#include +#endif + FILE * fopen(const char *filename, const char *mode) { @@ -76,6 +80,17 @@ fopen(const char *filename, const char *mode) return (NULL); } +#ifdef LOADER_VERIEXEC + /* only regular files and only reading makes sense */ + if (S_ISREG(st.st_mode) && !(m & O_WRONLY)) { + if (verify_file(fd, filename, 0, VE_GUESS) < 0) { + free(f); + close(fd); + return (NULL); + } + } +#endif + f->fd = fd; f->offset = 0; f->size = st.st_size; diff --git a/stand/libsa/Makefile b/stand/libsa/Makefile index 95cededc3233..0038075c4710 100644 --- a/stand/libsa/Makefile +++ b/stand/libsa/Makefile @@ -164,6 +164,11 @@ SRCS+= explicit_bzero.c crc32_libkern.c .include "${SASRC}/geli/Makefile.inc" .endif +.if ${MK_LOADER_VERIEXEC} == "yes" && ${MK_BEARSSL} == "yes" +.include "${SRCTOP}/lib/libbearssl/Makefile.libsa.inc" +.include "${SRCTOP}/lib/libsecureboot/Makefile.libsa.inc" +.endif + # Maybe ZFS .if ${MK_LOADER_ZFS} == "yes" .include "${SASRC}/zfs/Makefile.inc" diff --git a/stand/libsa/Makefile.depend b/stand/libsa/Makefile.depend index 1d86fce1441d..f80275d86ab1 100644 --- a/stand/libsa/Makefile.depend +++ b/stand/libsa/Makefile.depend @@ -2,10 +2,6 @@ # Autogenerated - do NOT edit! DIRDEPS = \ - include \ - include/arpa \ - include/xlocale \ - lib/libbz2 \ .include diff --git a/stand/libsa32/Makefile.depend b/stand/libsa32/Makefile.depend index 1d86fce1441d..73bc18c8c0fc 100644 --- a/stand/libsa32/Makefile.depend +++ b/stand/libsa32/Makefile.depend @@ -2,10 +2,7 @@ # Autogenerated - do NOT edit! DIRDEPS = \ - include \ - include/arpa \ - include/xlocale \ - lib/libbz2 \ + stand/libsa \ .include diff --git a/stand/loader.mk b/stand/loader.mk index e5149191fb47..2efac31b615f 100644 --- a/stand/loader.mk +++ b/stand/loader.mk @@ -73,6 +73,10 @@ SRCS+= interp_simple.c .error Unknown interpreter ${LOADER_INTERP} .endif +.if ${MK_LOADER_VERIEXEC} != "no" +CFLAGS+= -DLOADER_VERIEXEC -I${SRCTOP}/lib/libsecureboot/h +.endif + .if defined(BOOT_PROMPT_123) CFLAGS+= -DBOOT_PROMPT_123 .endif