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
This commit is contained in:
Simon J. Gerraty 2019-02-26 06:22:10 +00:00
parent eb12b8ea5e
commit 8df8b2d3e5
18 changed files with 117 additions and 30 deletions

View File

@ -106,6 +106,10 @@ command_boot(int argc, char *argv[])
if (archsw.arch_autoload() != 0) if (archsw.arch_autoload() != 0)
return(CMD_ERROR); return(CMD_ERROR);
#ifdef LOADER_VERIEXEC
verify_pcr_export(); /* for measured boot */
#endif
/* Call the exec handler from the loader matching the kernel */ /* Call the exec handler from the loader matching the kernel */
file_formats[fp->f_loader]->l_exec(fp); file_formats[fp->f_loader]->l_exec(fp);
return(CMD_ERROR); return(CMD_ERROR);

View File

@ -330,6 +330,9 @@ struct arch_switch
/* Probe ZFS pool(s), if needed. */ /* Probe ZFS pool(s), if needed. */
void (*arch_zfs_probe)(void); 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 */ /* For kexec-type loaders, get ksegment structure */
void (*arch_kexec_kseg_get)(int *nseg, void **kseg); 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") #define CTASSERT(x) _Static_assert(x, "compile-time assertion failed")
#endif #endif
#ifdef LOADER_VERIEXEC
#include <verify_file.h>
#endif
#endif /* !_BOOTSTRAP_H_ */ #endif /* !_BOOTSTRAP_H_ */

View File

@ -379,6 +379,13 @@ interp_include(const char *filename)
return(CMD_ERROR); 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. * Read the script into memory.
*/ */

View File

@ -96,6 +96,14 @@ interp_include(const char *filename)
return(CMD_ERROR); 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. * Read the script into memory.
*/ */

View File

@ -245,6 +245,12 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef)
goto error; goto error;
} }
#ifdef LOADER_VERIEXEC
if (verify_file(ef->fd, filename, bytes_read, VE_MUST) < 0) {
err = EAUTH;
goto error;
}
#endif
return (0); return (0);
error: error:

View File

@ -129,6 +129,13 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest,
goto oerr; 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)); kfp = file_findfile(NULL, __elfN(obj_kerneltype));
if (kfp == NULL) { if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) printf("elf" __XSTRING(__ELF_WORD_SIZE)

View File

@ -104,6 +104,8 @@ command_load(int argc, char *argv[])
{ {
struct preloaded_file *fp; struct preloaded_file *fp;
char *typestr; char *typestr;
char *prefix;
char *skip;
int dofile, dokld, ch, error; int dofile, dokld, ch, error;
dokld = dofile = 0; dokld = dofile = 0;
@ -114,11 +116,18 @@ command_load(int argc, char *argv[])
command_errmsg = "no filename specified"; command_errmsg = "no filename specified";
return (CMD_CRIT); return (CMD_CRIT);
} }
while ((ch = getopt(argc, argv, "kt:")) != -1) { prefix = skip = NULL;
while ((ch = getopt(argc, argv, "kp:s:t:")) != -1) {
switch(ch) { switch(ch) {
case 'k': case 'k':
dokld = 1; dokld = 1;
break; break;
case 'p':
prefix = optarg;
break;
case 's':
skip = optarg;
break;
case 't': case 't':
typestr = optarg; typestr = optarg;
dofile = 1; dofile = 1;
@ -141,6 +150,12 @@ command_load(int argc, char *argv[])
return (CMD_CRIT); 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); fp = file_findfile(argv[1], typestr);
if (fp) { if (fp) {
snprintf(command_errbuf, sizeof(command_errbuf), snprintf(command_errbuf, sizeof(command_errbuf),
@ -435,6 +450,15 @@ file_loadraw(const char *fname, char *type, int insert)
return(NULL); 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) if (archsw.arch_loadaddr != NULL)
loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr); loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);

View File

@ -2,9 +2,7 @@
# Autogenerated - do NOT edit! # Autogenerated - do NOT edit!
DIRDEPS = \ DIRDEPS = \
include \ stand/libsa \
include/xlocale \
lib/msun \
.include <dirdeps.mk> .include <dirdeps.mk>

View File

@ -1157,6 +1157,10 @@ typedef void ficlCompileFcn(FICL_SYSTEM *);
DATA_SET(Xficl_compile_set, func) DATA_SET(Xficl_compile_set, func)
SET_DECLARE(Xficl_compile_set, ficlCompileFcn); SET_DECLARE(Xficl_compile_set, ficlCompileFcn);
#ifdef LOADER_VERIEXEC
#include <verify_file.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -67,14 +67,21 @@ static void ficlFopen(FICL_VM *pVM, char *writeMode) /* ( c-addr u fam -- fileid
if (f == NULL) if (f == NULL)
stackPushPtr(pVM->pStack, NULL); stackPushPtr(pVM->pStack, NULL);
else 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)); ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE));
strcpy(ff->filename, filename); strcpy(ff->filename, filename);
ff->f = f; ff->f = f;
stackPushPtr(pVM->pStack, ff); stackPushPtr(pVM->pStack, ff);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
} }
pushIor(pVM, f != NULL); pushIor(pVM, f != NULL);
} }

View File

@ -2,9 +2,7 @@
# Autogenerated - do NOT edit! # Autogenerated - do NOT edit!
DIRDEPS = \ DIRDEPS = \
include \ stand/libsa \
include/xlocale \
lib/msun \
.include <dirdeps.mk> .include <dirdeps.mk>

View File

@ -2,15 +2,12 @@
# Autogenerated - do NOT edit! # Autogenerated - do NOT edit!
DIRDEPS = \ DIRDEPS = \
include \ stand/${MACHINE_CPUARCH}/btx/btx \
include/xlocale \ stand/${MACHINE_CPUARCH}/btx/btxldr \
stand/ficl32 \ stand/${MACHINE_CPUARCH}/btx/lib \
stand/geli \ stand/${MACHINE_CPUARCH}/libi386 \
stand/i386/btx/btx \ stand/ficl \
stand/i386/btx/btxldr \ stand/libsa \
stand/i386/btx/lib \
stand/i386/libi386 \
stand/libsa32 \
.include <dirdeps.mk> .include <dirdeps.mk>

View File

@ -35,5 +35,8 @@ CFLAGS+= -I${BOOTSRC}/include -I${LIBLUASRC} -I${LUASRC} -I${LDRSRC}
.if ${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 0 .if ${MACHINE_CPUARCH} == "amd64" && ${DO32:U0} == 0
CFLAGS+= -fPIC CFLAGS+= -fPIC
.endif .endif
.if ${MK_LOADER_VERIEXEC} == "yes"
CFLAGS+= -I${SRCTOP}/lib/libsecureboot/h -DLOADER_VERIEXEC
.endif
.include <bsd.lib.mk> .include <bsd.lib.mk>

View File

@ -31,6 +31,10 @@ __FBSDID("$FreeBSD$");
#include "lstd.h" #include "lstd.h"
#include "math.h" #include "math.h"
#ifdef LOADER_VERIEXEC
#include <verify_file.h>
#endif
FILE * FILE *
fopen(const char *filename, const char *mode) fopen(const char *filename, const char *mode)
{ {
@ -76,6 +80,17 @@ fopen(const char *filename, const char *mode)
return (NULL); 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->fd = fd;
f->offset = 0; f->offset = 0;
f->size = st.st_size; f->size = st.st_size;

View File

@ -164,6 +164,11 @@ SRCS+= explicit_bzero.c crc32_libkern.c
.include "${SASRC}/geli/Makefile.inc" .include "${SASRC}/geli/Makefile.inc"
.endif .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 # Maybe ZFS
.if ${MK_LOADER_ZFS} == "yes" .if ${MK_LOADER_ZFS} == "yes"
.include "${SASRC}/zfs/Makefile.inc" .include "${SASRC}/zfs/Makefile.inc"

View File

@ -2,10 +2,6 @@
# Autogenerated - do NOT edit! # Autogenerated - do NOT edit!
DIRDEPS = \ DIRDEPS = \
include \
include/arpa \
include/xlocale \
lib/libbz2 \
.include <dirdeps.mk> .include <dirdeps.mk>

View File

@ -2,10 +2,7 @@
# Autogenerated - do NOT edit! # Autogenerated - do NOT edit!
DIRDEPS = \ DIRDEPS = \
include \ stand/libsa \
include/arpa \
include/xlocale \
lib/libbz2 \
.include <dirdeps.mk> .include <dirdeps.mk>

View File

@ -73,6 +73,10 @@ SRCS+= interp_simple.c
.error Unknown interpreter ${LOADER_INTERP} .error Unknown interpreter ${LOADER_INTERP}
.endif .endif
.if ${MK_LOADER_VERIEXEC} != "no"
CFLAGS+= -DLOADER_VERIEXEC -I${SRCTOP}/lib/libsecureboot/h
.endif
.if defined(BOOT_PROMPT_123) .if defined(BOOT_PROMPT_123)
CFLAGS+= -DBOOT_PROMPT_123 CFLAGS+= -DBOOT_PROMPT_123
.endif .endif