From 19815ded6503c7e91e54f20f67ba16f72f74fe52 Mon Sep 17 00:00:00 2001 From: "Simon J. Gerraty" Date: Thu, 9 Apr 2020 04:50:19 +0000 Subject: [PATCH] veloader use vectx API for kernel and modules The vectx API, computes the hash for verifying a file as it is read. This avoids the overhead of reading files twice - once to verify, then again to load. For doing an install via loader, avoiding the need to rewind large files is critical. This API is only used for modules, kernel and mdimage as these are the biggest files read by the loader. The reduction in boot time depends on how expensive the I/O is on any given platform. On a fast VM we see 6% improvement. For install via loader the first file to be verified is likely to be the kernel, so some of the prep work (finding manifest etc) done by verify_file() needs to be factored so it can be reused for vectx_open(). For missing or unrecognized fingerprint entries, we fail in vectx_open() unless verifying is disabled. Otherwise fingerprint check happens in vectx_close() and since this API is only used for files which must be verified (VE_MUST) we panic if we get an incorrect hash. Fix pkgfs stat so it satisfies libsecureboot We need a valid st_dev, st_ino and st_mtime to correctly track which files have been verified and to update our notion of time. ve_utc_set(): ignore utc if it would jump our current time by more than VE_UTC_MAX_JUMP (20 years). Allow testing of install command via userboot. Need to fix its stat implementation too. bhyveload also needs stat fixed - due to change to userboot.h Call ve_error_get() from vectx_close() when hash is wrong. Track the names of files we have hashed into pcr For the purposes of measured boot, it is important to be able to reproduce the hash reflected in loader.ve.pcr so loader.ve.hashed provides a list of names in the order they were added. Avoid unused vars when VE_ECDSA_HASH_AGAIN undefined MFC of r358744 r358767 r359307 r355962 Reviewed by: imp,tsoome,emaste Sponsored by: Juniper Networks Differential Revision: https://reviews.freebsd.org//D23827 https://reviews.freebsd.org//D24027 --- lib/libsecureboot/h/libsecureboot.h | 9 +- lib/libsecureboot/h/verify_file.h | 24 +++-- lib/libsecureboot/tests/tvo.c | 20 +++- lib/libsecureboot/vectx.c | 112 ++++++++++++++++---- lib/libsecureboot/veopen.c | 8 +- lib/libsecureboot/vepcr.c | 79 ++++++++++++-- lib/libsecureboot/verify_file.c | 141 ++++++++++++++++++------- lib/libsecureboot/vets.c | 23 ++-- share/mk/src.opts.mk | 1 + stand/common/bootstrap.h | 12 +-- stand/common/install.c | 11 ++ stand/common/interp_forth.c | 4 +- stand/common/interp_simple.c | 2 +- stand/common/load_elf.c | 86 +++++++++++---- stand/common/load_elf_obj.c | 47 +++++++-- stand/common/misc.c | 10 +- stand/common/module.c | 43 +++++++- stand/common/readin.h | 43 ++++++++ stand/efi/loader/arch/i386/i386_copy.c | 5 +- stand/efi/loader/copy.c | 4 +- stand/efi/loader/loader_efi.h | 3 +- stand/efi/loader/main.c | 8 ++ stand/ficl/loader.c | 2 +- stand/i386/libi386/i386_copy.c | 4 +- stand/i386/libi386/libi386.h | 4 +- stand/i386/loader/chain.c | 37 ++++++- stand/libsa/pkgfs.c | 19 +++- stand/loader.mk | 3 + stand/mips/beri/loader/arch.c | 6 +- stand/powerpc/kboot/main.c | 8 +- stand/uboot/lib/copy.c | 4 +- stand/uboot/lib/libuboot.h | 3 +- stand/userboot/test/test.c | 17 +-- stand/userboot/userboot.h | 3 +- stand/userboot/userboot/conf.c | 5 + stand/userboot/userboot/copy.c | 4 +- stand/userboot/userboot/host.c | 12 +-- stand/userboot/userboot/libuserboot.h | 3 +- usr.sbin/bhyveload/bhyveload.c | 15 ++- 39 files changed, 654 insertions(+), 190 deletions(-) create mode 100644 stand/common/readin.h diff --git a/lib/libsecureboot/h/libsecureboot.h b/lib/libsecureboot/h/libsecureboot.h index d7d72e88074..33f98bca047 100644 --- a/lib/libsecureboot/h/libsecureboot.h +++ b/lib/libsecureboot/h/libsecureboot.h @@ -69,12 +69,6 @@ void fingerprint_info_add(const char *, const char *, const char *, int ve_check_hash(br_hash_compat_context *, const br_hash_class *, const char *, const char *, size_t); -struct vectx; -struct vectx* vectx_open(int, const char *, off_t, struct stat *, int *); -ssize_t vectx_read(struct vectx *, void *, size_t); -off_t vectx_lseek(struct vectx *, off_t, int); -int vectx_close(struct vectx *); - char * hexdigest(char *, size_t, unsigned char *, size_t); int verify_fd(int, const char *, off_t, struct stat *); int verify_open(const char *, int); @@ -84,10 +78,11 @@ unsigned char *verify_sig(const char *, int); unsigned char *verify_asc(const char *, int); /* OpenPGP */ void ve_pcr_init(void); -void ve_pcr_update(unsigned char *, size_t); +void ve_pcr_update(const char *, unsigned char *, size_t); ssize_t ve_pcr_get(unsigned char *, size_t); int ve_pcr_updating_get(void); void ve_pcr_updating_set(int); +char * ve_pcr_hashed_get(int); /* flags for verify_{asc,sig,signed} */ #define VEF_VERBOSE 1 diff --git a/lib/libsecureboot/h/verify_file.h b/lib/libsecureboot/h/verify_file.h index c10f17af146..844b8266f42 100644 --- a/lib/libsecureboot/h/verify_file.h +++ b/lib/libsecureboot/h/verify_file.h @@ -39,13 +39,21 @@ struct stat; -void ve_debug_set(int); -int ve_status_get(int); -void ve_efi_init(void); -int load_manifest(const char *, const char *, const char *, struct stat *); -int pass_manifest(const char *, const char *); -int pass_manifest_export_envs(void); -int verify_file(int, const char *, off_t, int); -void verify_pcr_export(void); +int verify_prep(int, const char *, off_t, struct stat *, const char *); +void ve_debug_set(int); +char *ve_error_get(void); +void ve_efi_init(void); +int ve_status_get(int); +int load_manifest(const char *, const char *, const char *, struct stat *); +int pass_manifest(const char *, const char *); +int pass_manifest_export_envs(void); +int verify_file(int, const char *, off_t, int, const char *); +void verify_pcr_export(void); + +struct vectx; +struct vectx* vectx_open(int, const char *, off_t, struct stat *, int *, const char *); +ssize_t vectx_read(struct vectx *, void *, size_t); +off_t vectx_lseek(struct vectx *, off_t, int); +int vectx_close(struct vectx *, int, const char *); #endif /* _VERIFY_FILE_H_ */ diff --git a/lib/libsecureboot/tests/tvo.c b/lib/libsecureboot/tests/tvo.c index ad3bccb0614..879d87f128f 100644 --- a/lib/libsecureboot/tests/tvo.c +++ b/lib/libsecureboot/tests/tvo.c @@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$"); #include #include +size_t DestdirLen; +char *Destdir; char *Skip; int @@ -42,7 +44,10 @@ main(int argc, char *argv[]) int Vflag; char *cp; char *prefix; + char *destdir; + Destdir = NULL; + DestdirLen = 0; prefix = NULL; Skip = NULL; @@ -50,8 +55,12 @@ main(int argc, char *argv[]) printf("Trust %d\n", n); Vflag = 0; - while ((c = getopt(argc, argv, "dp:s:T:V")) != -1) { + while ((c = getopt(argc, argv, "D:dp:s:T:V")) != -1) { switch (c) { + case 'D': + Destdir = optarg; + DestdirLen = strlen(optarg); + break; case 'd': DebugVe++; break; @@ -92,7 +101,7 @@ main(int argc, char *argv[]) */ int x; - x = verify_file(fd, argv[optind], 0, VE_GUESS); + x = verify_file(fd, argv[optind], 0, VE_GUESS, __func__); printf("verify_file(%s) = %d\n", argv[optind], x); close(fd); } @@ -147,7 +156,7 @@ main(int argc, char *argv[]) lseek(fd, 0, SEEK_SET); off = st.st_size % 512; vp = vectx_open(fd, argv[optind], off, - &st, &error); + &st, &error, __func__); if (!vp) { printf("vectx_open(%s) failed: %d %s\n", argv[optind], error, @@ -155,7 +164,8 @@ main(int argc, char *argv[]) } else { off = vectx_lseek(vp, (st.st_size % 1024), SEEK_SET); - + /* we can seek backwards! */ + off = vectx_lseek(vp, off/2, SEEK_SET); if (off < st.st_size) { n = vectx_read(vp, buf, sizeof(buf)); @@ -165,7 +175,7 @@ main(int argc, char *argv[]) off = vectx_lseek(vp, 0, SEEK_END); /* repeating that should be harmless */ off = vectx_lseek(vp, 0, SEEK_END); - error = vectx_close(vp); + error = vectx_close(vp, VE_MUST, __func__); if (error) { printf("vectx_close(%s) == %d %s\n", argv[optind], error, diff --git a/lib/libsecureboot/vectx.c b/lib/libsecureboot/vectx.c index 97a8d97efb8..433df00f244 100644 --- a/lib/libsecureboot/vectx.c +++ b/lib/libsecureboot/vectx.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #endif #include "libsecureboot-priv.h" +#include /** * @file vectx.c @@ -50,12 +51,14 @@ struct vectx { const char *vec_path; /* path we are verifying */ const char *vec_want; /* hash value we want */ off_t vec_off; /* current offset */ + off_t vec_hashed; /* where we have hashed to */ size_t vec_size; /* size of path */ size_t vec_hashsz; /* size of hash */ int vec_fd; /* file descriptor */ int vec_status; /* verification status */ }; + /** * @brief * verify an open file as we read it @@ -86,24 +89,31 @@ struct vectx { * NULL is only returned for non-files or out-of-memory. */ struct vectx * -vectx_open(int fd, const char *path, off_t off, struct stat *stp, int *error) +vectx_open(int fd, const char *path, off_t off, struct stat *stp, + int *error, const char *caller) { struct vectx *ctx; struct stat st; size_t hashsz; char *cp; + int rc; - if (!stp) { - if (fstat(fd, &st) == 0) - stp = &st; - } + if (!stp) + stp = &st; - /* we *should* only get called for files */ - if (stp && !S_ISREG(stp->st_mode)) { - *error = 0; + rc = verify_prep(fd, path, off, stp, __func__); + + DEBUG_PRINTF(2, + ("vectx_open: caller=%s,fd=%d,name='%s',prep_rc=%d\n", + caller, fd, path, rc)); + + switch (rc) { + case VE_FINGERPRINT_NONE: + case VE_FINGERPRINT_UNKNOWN: + case VE_FINGERPRINT_WRONG: + *error = rc; return (NULL); } - ctx = malloc(sizeof(struct vectx)); if (!ctx) goto enomem; @@ -111,10 +121,16 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp, int *error) ctx->vec_path = path; ctx->vec_size = stp->st_size; ctx->vec_off = 0; + ctx->vec_hashed = 0; ctx->vec_want = NULL; ctx->vec_status = 0; - hashsz = 0; + ctx->vec_hashsz = hashsz = 0; + if (rc == 0) { + /* we are not verifying this */ + *error = 0; + return (ctx); + } cp = fingerprint_info_lookup(fd, path); if (!cp) { ctx->vec_status = VE_FINGERPRINT_NONE; @@ -161,6 +177,10 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp, int *error) vectx_lseek(ctx, off, SEEK_SET); } } + DEBUG_PRINTF(2, + ("vectx_open: caller=%s,name='%s',hashsz=%lu,status=%d\n", + caller, path, (unsigned long)ctx->vec_hashsz, + ctx->vec_status)); return (ctx); enomem: /* unlikely */ @@ -175,6 +195,8 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp, int *error) * * It is critical that all file I/O comes through here. * We keep track of current offset. + * We also track what offset we have hashed to, + * so we won't replay data if we seek backwards. * * @param[in] pctx * pointer to ctx @@ -190,6 +212,8 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes) { unsigned char *bp = buf; int n; + int delta; + int x; size_t off; if (ctx->vec_hashsz == 0) /* nothing to do */ @@ -201,9 +225,20 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes) if (n < 0) return (n); if (n > 0) { - ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], n); - off += n; - ctx->vec_off += n; + /* we may have seeked backwards! */ + delta = ctx->vec_hashed - ctx->vec_off; + if (delta > 0) { + x = MIN(delta, n); + off += x; + n -= x; + ctx->vec_off += x; + } + if (n > 0) { + ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], n); + off += n; + ctx->vec_off += n; + ctx->vec_hashed += n; + } } } while (n > 0 && off < nbytes); return (off); @@ -213,10 +248,10 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes) * @brief * vectx equivalent of lseek * - * We do not actually, seek, but call vectx_read + * When seeking forwards we actually call vectx_read * to reach the desired offset. * - * We do not support seeking backwards. + * We support seeking backwards. * * @param[in] pctx * pointer to ctx @@ -225,6 +260,8 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes) * desired offset * * @param[in] whence + * We try to convert whence to ``SEEK_SET``. + * We do not support ``SEEK_DATA`` or ``SEEK_HOLE``. * * @return offset or error. */ @@ -239,22 +276,26 @@ vectx_lseek(struct vectx *ctx, off_t off, int whence) return (lseek(ctx->vec_fd, off, whence)); /* - * Try to convert whence to SEEK_SET - * but we cannot support seeking backwards! - * Nor beyond end of file. + * Convert whence to SEEK_SET */ if (whence == SEEK_END && off <= 0) { whence = SEEK_SET; off += ctx->vec_size; - } else if (whence == SEEK_CUR && off >= 0) { + } else if (whence == SEEK_CUR) { whence = SEEK_SET; off += ctx->vec_off; } - if (whence != SEEK_SET || off < ctx->vec_off || + if (whence != SEEK_SET || (size_t)off > ctx->vec_size) { - printf("ERROR: %s: unsupported operation\n", __func__); + printf("ERROR: %s: unsupported operation: whence=%d off=%lld -> %lld\n", + __func__, whence, (long long)ctx->vec_off, (long long)off); return (-1); } + if (off < ctx->vec_hashed) { + /* seeking backwards! just do it */ + ctx->vec_off = lseek(ctx->vec_fd, off, whence); + return (ctx->vec_off); + } n = 0; do { delta = off - ctx->vec_off; @@ -275,22 +316,49 @@ vectx_lseek(struct vectx *ctx, off_t off, int whence) * We have finished reading file, compare the hash with what * we wanted. * + * Be sure to call this before closing the file, since we may + * need to seek to the end to ensure hashing is complete. + * * @param[in] pctx * pointer to ctx * * @return 0 or an error. */ int -vectx_close(struct vectx *ctx) +vectx_close(struct vectx *ctx, int severity, const char *caller) { int rc; if (ctx->vec_hashsz == 0) { rc = ctx->vec_status; } else { +#ifdef VE_PCR_SUPPORT + /* + * Only update pcr with things that must verify + * these tend to be processed in a more deterministic + * order, which makes our pseudo pcr more useful. + */ + ve_pcr_updating_set((severity == VE_MUST)); +#endif + /* make sure we have hashed it all */ + vectx_lseek(ctx, 0, SEEK_END); rc = ve_check_hash(&ctx->vec_ctx, ctx->vec_md, ctx->vec_path, ctx->vec_want, ctx->vec_hashsz); } + DEBUG_PRINTF(2, + ("vectx_close: caller=%s,name='%s',rc=%d,severity=%d\n", + caller,ctx->vec_path, rc, severity)); + if (rc == VE_FINGERPRINT_WRONG) { + printf("Unverified: %s\n", ve_error_get()); +#if !defined(UNIT_TEST) && !defined(DEBUG_VECTX) + /* we are generally called with VE_MUST */ + if (severity > VE_WANT) + panic("cannot continue"); +#endif + } else if (severity > VE_WANT) { + printf("%serified %s\n", (rc <= 0) ? "Unv" : "V", + ctx->vec_path); + } free(ctx); return ((rc < 0) ? rc : 0); } diff --git a/lib/libsecureboot/veopen.c b/lib/libsecureboot/veopen.c index 6ecf85c44af..da6291504c4 100644 --- a/lib/libsecureboot/veopen.c +++ b/lib/libsecureboot/veopen.c @@ -86,9 +86,11 @@ fingerprint_info_add(const char *filename, const char *prefix, } nfip->fi_prefix = strdup(filename); cp = strrchr(nfip->fi_prefix, '/'); - if (cp) + if (cp == nfip->fi_prefix) { + cp[1] = '\0'; + } else if (cp) { *cp = '\0'; - else { + } else { free(nfip->fi_prefix); free(nfip); return; @@ -96,7 +98,7 @@ fingerprint_info_add(const char *filename, const char *prefix, } /* collapse any trailing ..[/] */ n = 0; - while ((cp = strrchr(nfip->fi_prefix, '/')) != NULL) { + while ((cp = strrchr(nfip->fi_prefix, '/')) > nfip->fi_prefix) { if (cp[1] == '\0') { /* trailing "/" */ *cp = '\0'; continue; diff --git a/lib/libsecureboot/vepcr.c b/lib/libsecureboot/vepcr.c index a97cb724583..88128647b08 100644 --- a/lib/libsecureboot/vepcr.c +++ b/lib/libsecureboot/vepcr.c @@ -25,6 +25,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include "libsecureboot-priv.h" /* @@ -43,7 +44,16 @@ __FBSDID("$FreeBSD$"); static const br_hash_class *pcr_md = NULL; static br_hash_compat_context pcr_ctx; static size_t pcr_hlen = 0; -static int pcr_updating; +static int pcr_updating = -1; + +struct hashed_info { + const char *hi_path; + const char *hi_basename; + STAILQ_ENTRY(hashed_info) entries; +}; + +static STAILQ_HEAD(, hashed_info) hi_list; + /** * @brief initialize pcr context @@ -54,10 +64,13 @@ static int pcr_updating; void ve_pcr_init(void) { - pcr_updating = 0; - pcr_hlen = br_sha256_SIZE; - pcr_md = &br_sha256_vtable; - pcr_md->init(&pcr_ctx.vtable); + if (pcr_updating < 0) { + pcr_updating = 0; + pcr_hlen = br_sha256_SIZE; + pcr_md = &br_sha256_vtable; + pcr_md->init(&pcr_ctx.vtable); + STAILQ_INIT(&hi_list); + } } /** @@ -82,10 +95,28 @@ ve_pcr_updating_set(int updating) * @brief update pcr context */ void -ve_pcr_update(unsigned char *data, size_t dlen) +ve_pcr_update(const char *path, unsigned char *data, size_t dlen) { - if (pcr_updating != 0 && pcr_md != NULL) + struct hashed_info *hip; + + if (pcr_updating > 0 && pcr_md != NULL) { pcr_md->update(&pcr_ctx.vtable, data, dlen); + /* if mallocs fail, measured boot will likely fail too */ + if ((hip = malloc(sizeof(struct hashed_info)))) { + hip->hi_path = strdup(path); + if (!hip->hi_path) { + free(hip); + return; + } + hip->hi_basename = strrchr(hip->hi_path, '/'); + if (hip->hi_basename) { + hip->hi_basename++; + } else { + hip->hi_basename = hip->hi_path; + } + STAILQ_INSERT_TAIL(&hi_list, hip, entries); + } + } } /** @@ -102,3 +133,37 @@ ve_pcr_get(unsigned char *buf, size_t sz) return (pcr_hlen); } +/** + * @brief get list of paths in prc + */ +char * +ve_pcr_hashed_get(int flags) +{ + const char *cp; + char *hinfo; + struct hashed_info *hip; + size_t nbytes; + size_t x; + int n; + + n = 0; + nbytes = x = 0; + hinfo = NULL; + STAILQ_FOREACH(hip, &hi_list, entries) { + nbytes += 1 + strlen(flags ? hip->hi_basename : hip->hi_path); + } + if (nbytes > 1) { + hinfo = malloc(nbytes + 2); + if (hinfo) { + STAILQ_FOREACH(hip, &hi_list, entries) { + cp = flags ? hip->hi_basename : hip->hi_path; + n = snprintf(&hinfo[x], nbytes - x, "%s,", cp); + x += n; + } + if (x > 0) { + hinfo[x-1] = '\0'; + } + } + } + return hinfo; +} diff --git a/lib/libsecureboot/verify_file.c b/lib/libsecureboot/verify_file.c index 92845fb6879..20fc0ae4ae7 100644 --- a/lib/libsecureboot/verify_file.c +++ b/lib/libsecureboot/verify_file.c @@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$"); * define MANIFEST_SKIP to Skip - in tests/tvo.c so that * tvo can control the value we use in find_manifest() */ +extern char *Destdir; +extern size_t DestdirLen; extern char *Skip; # undef MANIFEST_SKIP # define MANIFEST_SKIP Skip @@ -115,10 +117,12 @@ is_verified(struct stat *stp) { struct verify_status *vsp; - for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) { - if (stp->st_dev == vsp->vs_dev && - stp->st_ino == vsp->vs_ino) - return (vsp->vs_status); + if (stp->st_ino > 0) { + for (vsp = verified_files; vsp != NULL; vsp = vsp->vs_next) { + if (stp->st_dev == vsp->vs_dev && + stp->st_ino == vsp->vs_ino) + return (vsp->vs_status); + } } return (VE_NOT_CHECKED); } @@ -167,12 +171,21 @@ load_manifest(const char *name, const char *prefix, ve_utc_set(stp->st_mtime); content = (char *)verify_signed(name, VEF_VERBOSE); if (content) { +#ifdef UNIT_TEST + if (DestdirLen > 0 && + strncmp(name, Destdir, DestdirLen) == 0) { + name += DestdirLen; + if (prefix && + strncmp(prefix, Destdir, DestdirLen) == 0) + prefix += DestdirLen; + } +#endif fingerprint_info_add(name, prefix, skip, content, stp); add_verify_status(stp, VE_VERIFIED); loaded_manifests = 1; /* we are verifying! */ DEBUG_PRINTF(3, ("loaded: %s %s %s\n", name, prefix, skip)); - rc = 0; + rc = VE_VERIFIED; } else { rc = VE_FINGERPRINT_WRONG; add_verify_status(stp, rc); /* remember */ @@ -245,13 +258,15 @@ severity_guess(const char *filename) return (VE_WANT); } +static int Verifying = -1; /* 0 if not verifying */ + static void verify_tweak(int fd, off_t off, struct stat *stp, char *tweak, int *accept_no_fp, - int *verbose, int *verifying) + int *verbose) { if (strcmp(tweak, "off") == 0) { - *verifying = 0; + Verifying = 0; } else if (strcmp(tweak, "strict") == 0) { /* anything caller wants verified must be */ *accept_no_fp = VE_WANT; @@ -314,6 +329,59 @@ getenv_int(const char *var, int def) return (int)val; } + +/** + * @brief prepare to verify an open file + * + * @param[in] fd + * open descriptor + * + * @param[in] filename + * path we opened and will use to lookup fingerprint + * + * @param[in] stp + * stat pointer so we can check file type + */ +int +verify_prep(int fd, const char *filename, off_t off, struct stat *stp, + const char *caller) +{ + int rc; + + if (Verifying < 0) { + Verifying = ve_trust_init(); +#ifndef UNIT_TEST + ve_debug_set(getenv_int("VE_DEBUG_LEVEL", VE_DEBUG_LEVEL)); +#endif + /* initialize ve_status with default result */ + rc = Verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING; + ve_status_set(0, rc); + ve_status_state = VE_STATUS_NONE; + if (Verifying) { + ve_self_tests(); + ve_anchor_verbose_set(1); + } + } + if (!Verifying || fd < 0) + return (0); + if (stp) { + if (fstat(fd, stp) < 0 || !S_ISREG(stp->st_mode)) + return (0); + } + DEBUG_PRINTF(2, + ("verify_prep: caller=%s,fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n", + caller, fd, filename, (long long)off, (long long)stp->st_dev, + (long long)stp->st_ino)); + rc = is_verified(stp); + DEBUG_PRINTF(4,("verify_prep: is_verified()->%d\n", rc)); + if (rc == VE_NOT_CHECKED) { + rc = find_manifest(filename); + } else { + ve_status_set(fd, rc); + } + return (rc); +} + /** * @brief verify an open file * @@ -342,45 +410,26 @@ getenv_int(const char *var, int def) * @return >= 0 on success < 0 on failure */ int -verify_file(int fd, const char *filename, off_t off, int severity) +verify_file(int fd, const char *filename, off_t off, int severity, + const char *caller) { - static int verifying = -1; + static int once; static int accept_no_fp = ACCEPT_NO_FP_DEFAULT; static int verbose = VE_VERBOSE_DEFAULT; struct stat st; char *cp; int rc; - if (verifying < 0) { - verifying = ve_trust_init(); - verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT); - ve_debug_set(getenv_int("VE_DEBUG_LEVEL", VE_DEBUG_LEVEL)); - /* initialize ve_status with default result */ - rc = verifying ? VE_NOT_CHECKED : VE_NOT_VERIFYING; - ve_status_set(0, rc); - ve_status_state = VE_STATUS_NONE; - if (verifying) { - ve_self_tests(); - ve_anchor_verbose_set(1); - } - } - if (!verifying) - return (0); + rc = verify_prep(fd, filename, off, &st, caller); - if (fd < 0 || fstat(fd, &st) < 0 || !S_ISREG(st.st_mode)) + if (!rc) return (0); - DEBUG_PRINTF(3, ("fd=%d,name='%s',off=%lld,dev=%lld,ino=%lld\n", - fd, filename, (long long)off, (long long)st.st_dev, - (long long)st.st_ino)); - - - rc = is_verified(&st); - if (rc != VE_NOT_CHECKED) { - ve_status_set(fd, rc); - return (rc); + if (!once) { + once++; + verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT); } - rc = find_manifest(filename); + if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) { if (severity <= VE_GUESS) severity = severity_guess(filename); @@ -391,6 +440,12 @@ verify_file(int fd, const char *filename, off_t off, int severity) * order, which makes our pseudo pcr more useful. */ ve_pcr_updating_set((severity == VE_MUST)); +#endif +#ifdef UNIT_TEST + if (DestdirLen > 0 && + strncmp(filename, Destdir, DestdirLen) == 0) { + filename += DestdirLen; + } #endif if ((rc = verify_fd(fd, filename, off, &st)) >= 0) { if (verbose || severity > VE_WANT) { @@ -406,14 +461,12 @@ verify_file(int fd, const char *filename, off_t off, int severity) #endif } if (severity < VE_MUST) { /* not a kernel or module */ - if ((cp = strrchr(filename, '/'))) { cp++; if (strncmp(cp, "loader.ve.", 10) == 0) { cp += 10; verify_tweak(fd, off, &st, cp, - &accept_no_fp, &verbose, - &verifying); + &accept_no_fp, &verbose); } } } @@ -460,6 +513,7 @@ verify_pcr_export(void) #ifdef VE_PCR_SUPPORT char hexbuf[br_sha256_SIZE * 2 + 2]; unsigned char hbuf[br_sha256_SIZE]; + char *hinfo; char *hex; ssize_t hlen; @@ -469,6 +523,17 @@ verify_pcr_export(void) if (hex) { hex[hlen*2] = '\0'; /* clobber newline */ setenv("loader.ve.pcr", hex, 1); + DEBUG_PRINTF(1, + ("%s: setenv(loader.ve.pcr, %s\n", __func__, + hex)); + hinfo = ve_pcr_hashed_get(1); + if (hinfo) { + setenv("loader.ve.hashed", hinfo, 1); + DEBUG_PRINTF(1, + ("%s: setenv(loader.ve.hashed, %s\n", + __func__, hinfo)); + free(hinfo); + } } } #endif diff --git a/lib/libsecureboot/vets.c b/lib/libsecureboot/vets.c index c4d34ec6d4f..3a82592ea69 100644 --- a/lib/libsecureboot/vets.c +++ b/lib/libsecureboot/vets.c @@ -44,6 +44,10 @@ __FBSDID("$FreeBSD$"); #endif #define SECONDS_PER_DAY 86400 +#define SECONDS_PER_YEAR 365 * SECONDS_PER_DAY +#ifndef VE_UTC_MAX_JUMP +# define VE_UTC_MAX_JUMP 20 * SECONDS_PER_YEAR +#endif #define X509_DAYS_TO_UTC0 719528 int DebugVe = 0; @@ -113,12 +117,14 @@ static time_t ve_utc = 0; * set ve_utc used for certificate verification * * @param[in] utc - * time - ignored unless greater than current value. + * time - ignored unless greater than current value + * and not a leap of 20 years or more. */ void ve_utc_set(time_t utc) { - if (utc > ve_utc) { + if (utc > ve_utc && + (ve_utc == 0 || (utc - ve_utc) < VE_UTC_MAX_JUMP)) { DEBUG_PRINTF(2, ("Set ve_utc=%jd\n", (intmax_t)utc)); ve_utc = utc; } @@ -345,11 +351,11 @@ ve_trust_init(void) if (once >= 0) return (once); - - ve_utc_set(time(NULL)); + once = 0; /* to be sure */ #ifdef BUILD_UTC - ve_utc_set(BUILD_UTC); /* just in case */ + ve_utc_set(BUILD_UTC); /* ensure sanity */ #endif + ve_utc_set(time(NULL)); ve_error_set(NULL); /* make sure it is empty */ #ifdef VE_PCR_SUPPORT ve_pcr_init(); @@ -642,9 +648,10 @@ hexdigest(char *buf, size_t bufsz, unsigned char *foo, size_t foo_len) static unsigned char * verify_ec(br_x509_pkey *pk, const char *file, const char *sigfile) { - char hexbuf[br_sha512_SIZE * 2 + 2]; +#ifdef VE_ECDSA_HASH_AGAIN + char *hex, hexbuf[br_sha512_SIZE * 2 + 2]; +#endif unsigned char rhbuf[br_sha512_SIZE]; - char *hex; br_sha256_context ctx; unsigned char *fcp, *scp; size_t flen, slen, plen; @@ -902,7 +909,7 @@ ve_check_hash(br_hash_compat_context *ctx, const br_hash_class *md, md->out(&ctx->vtable, hbuf); #ifdef VE_PCR_SUPPORT - ve_pcr_update(hbuf, hlen); + ve_pcr_update(path, hbuf, hlen); #endif hex = hexdigest(hexbuf, sizeof(hexbuf), hbuf, hlen); if (!hex) diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index 6f06e07f945..c04a7bdc219 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -221,6 +221,7 @@ __DEFAULT_DEPENDENT_OPTIONS= \ CLANG_FULL/CLANG \ LOADER_VERIEXEC/BEARSSL \ LOADER_EFI_SECUREBOOT/LOADER_VERIEXEC \ + LOADER_VERIEXEC_VECTX/LOADER_VERIEXEC \ VERIEXEC/BEARSSL \ # MK_*_SUPPORT options which default to "yes" unless their corresponding diff --git a/stand/common/bootstrap.h b/stand/common/bootstrap.h index 3e723765104..2be6538efe4 100644 --- a/stand/common/bootstrap.h +++ b/stand/common/bootstrap.h @@ -33,6 +33,8 @@ #include #include +#include "readin.h" + /* Commands and return values; nonzero return sets command_errmsg != NULL */ typedef int (bootblk_cmd_t)(int argc, char *argv[]); #define COMMAND_ERRBUFSZ (256) @@ -70,8 +72,8 @@ void hexdump(caddr_t region, size_t len); size_t strlenout(vm_offset_t str); char *strdupout(vm_offset_t str); void kern_bzero(vm_offset_t dest, size_t len); -int kern_pread(int fd, vm_offset_t dest, size_t len, off_t off); -void *alloc_pread(int fd, off_t off, size_t len); +int kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off); +void *alloc_pread(readin_handle_t fd, off_t off, size_t len); /* bcache.c */ void bcache_init(size_t nblks, size_t bsize); @@ -303,7 +305,7 @@ struct arch_switch ssize_t (*arch_copyout)(const vm_offset_t src, void *dest, const size_t len); /* Read from file to module address space, same semantics as read() */ - ssize_t (*arch_readin)(const int fd, vm_offset_t dest, + ssize_t (*arch_readin)(readin_handle_t fd, vm_offset_t dest, const size_t len); /* Perform ISA byte port I/O (only for systems with ISA) */ int (*arch_isainb)(int port); @@ -349,8 +351,4 @@ 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/install.c b/stand/common/install.c index 0ba73e491b6..032006ec4fd 100644 --- a/stand/common/install.c +++ b/stand/common/install.c @@ -210,6 +210,13 @@ install(char *pkgname) if (currdev != NULL && strcmp(currdev, "pxe0:") == 0) { devname = "pxe0"; proto = NULL; +#ifdef HOSTPROG + } else if (currdev != NULL && strcmp(currdev, "host0:") == 0) { + extern struct fs_ops host_fsops; + + devname = "host0"; + proto = &host_fsops; +#endif } else { devname = "disk1"; proto = &dosfs_fsops; @@ -237,6 +244,10 @@ install(char *pkgname) setenv("serverip", inet_ntoa(servip), 1); + if (proto == &tftp_fsops) { + tftpip.s_addr = servip.s_addr; + } + *pkgname = '/'; } else pkgname = s; diff --git a/stand/common/interp_forth.c b/stand/common/interp_forth.c index 04b94ff20a1..19f1c75dc19 100644 --- a/stand/common/interp_forth.c +++ b/stand/common/interp_forth.c @@ -284,7 +284,7 @@ bf_init(void) /* try to load and run init file if present */ if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) { #ifdef LOADER_VERIEXEC - if (verify_file(fd, "/boot/boot.4th", 0, VE_GUESS) < 0) { + if (verify_file(fd, "/boot/boot.4th", 0, VE_GUESS, __func__) < 0) { close(fd); return; } @@ -386,7 +386,7 @@ interp_include(const char *filename) } #ifdef LOADER_VERIEXEC - if (verify_file(fd, filename, 0, VE_GUESS) < 0) { + if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) { close(fd); sprintf(command_errbuf,"can't verify '%s'", filename); return(CMD_ERROR); diff --git a/stand/common/interp_simple.c b/stand/common/interp_simple.c index 80d756f9dfe..e25743d4f01 100644 --- a/stand/common/interp_simple.c +++ b/stand/common/interp_simple.c @@ -97,7 +97,7 @@ interp_include(const char *filename) } #ifdef LOADER_VERIEXEC - if (verify_file(fd, filename, 0, VE_GUESS) < 0) { + if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) { close(fd); sprintf(command_errbuf,"can't verify '%s'", filename); return(CMD_ERROR); diff --git a/stand/common/load_elf.c b/stand/common/load_elf.c index 6b3ed719f7b..7139dc8b7c3 100644 --- a/stand/common/load_elf.c +++ b/stand/common/load_elf.c @@ -71,8 +71,17 @@ typedef struct elf_file { size_t firstlen; int kernel; uint64_t off; +#ifdef LOADER_VERIEXEC_VECTX + struct vectx *vctx; +#endif } *elf_file_t; +#ifdef LOADER_VERIEXEC_VECTX +#define VECTX_HANDLE(ef) (ef)->vctx +#else +#define VECTX_HANDLE(ef) (ef)->fd +#endif + static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, uint64_t loadaddr); static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, @@ -214,7 +223,20 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef) close(ef->fd); return (ENOMEM); } - bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE); +#ifdef LOADER_VERIEXEC_VECTX + { + int verror; + + ef->vctx = vectx_open(ef->fd, filename, 0L, NULL, &verror, __func__); + if (verror) { + printf("Unverified %s: %s\n", filename, ve_error_get()); + close(ef->fd); + free(ef->vctx); + return (EAUTH); + } + } +#endif + bytes_read = VECTX_READ(VECTX_HANDLE(ef), ef->firstpage, PAGE_SIZE); ef->firstlen = (size_t)bytes_read; if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) { err = EFTYPE; /* could be EIO, but may be small file */ @@ -245,10 +267,10 @@ __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; +#if defined(LOADER_VERIEXEC) && !defined(LOADER_VERIEXEC_VECTX) + if (verify_file(ef->fd, filename, bytes_read, VE_MUST, __func__) < 0) { + err = EAUTH; + goto error; } #endif return (0); @@ -259,6 +281,9 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef) ef->firstpage = NULL; } if (ef->fd != -1) { +#ifdef LOADER_VERIEXEC_VECTX + free(ef->vctx); +#endif close(ef->fd); ef->fd = -1; } @@ -415,8 +440,20 @@ __elfN(loadfile_raw)(char *filename, uint64_t dest, out: if (ef.firstpage) free(ef.firstpage); - if (ef.fd != -1) + if (ef.fd != -1) { +#ifdef LOADER_VERIEXEC_VECTX + if (!err && ef.vctx) { + int verror; + + verror = vectx_close(ef.vctx, VE_MUST, __func__); + if (verror) { + err = EAUTH; + file_discard(fp); + } + } +#endif close(ef.fd); + } return (err); } @@ -559,7 +596,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) phdr[i].p_vaddr + off, fpcopy); } if (phdr[i].p_filesz > fpcopy) { - if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy, + if (kern_pread(VECTX_HANDLE(ef), + phdr[i].p_vaddr + off + fpcopy, phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) @@ -603,7 +641,7 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) chunk = (size_t)ehdr->e_shnum * (size_t)ehdr->e_shentsize; if (chunk == 0 || ehdr->e_shoff == 0) goto nosyms; - shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk); + shdr = alloc_pread(VECTX_HANDLE(ef), ehdr->e_shoff, chunk); if (shdr == NULL) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: failed to read section headers"); @@ -622,8 +660,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) */ chunk = shdr[ehdr->e_shstrndx].sh_size; if (chunk) { - shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset, - chunk); + shstr = alloc_pread(VECTX_HANDLE(ef), + shdr[ehdr->e_shstrndx].sh_offset, chunk); if (shstr) { for (i = 0; i < ehdr->e_shnum; i++) { if (strcmp(shstr + shdr[i].sh_name, @@ -713,14 +751,14 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) printf("0x%lx+0x%lx", (long)sizeof(size), (long)size); #endif - if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { + if (VECTX_LSEEK(VECTX_HANDLE(ef), (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!"); lastaddr = ssym; ssym = 0; goto nosyms; } - result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size); + result = archsw.arch_readin(VECTX_HANDLE(ef), lastaddr, shdr[i].sh_size); if (result < 0 || (size_t)result != shdr[i].sh_size) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! " @@ -930,14 +968,14 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest) } size = (size_t)ef.ehdr->e_shnum * (size_t)ef.ehdr->e_shentsize; - shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size); + shdr = alloc_pread(VECTX_HANDLE(&ef), ef.ehdr->e_shoff, size); if (shdr == NULL) { err = ENOMEM; goto out; } /* Load shstrtab. */ - shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset, + shstrtab = alloc_pread(VECTX_HANDLE(&ef), shdr[ef.ehdr->e_shstrndx].sh_offset, shdr[ef.ehdr->e_shstrndx].sh_size); if (shstrtab == NULL) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) @@ -966,7 +1004,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest) } /* Load set_modmetadata_set into memory */ - err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset); + err = kern_pread(VECTX_HANDLE(&ef), dest, sh_meta->sh_size, sh_meta->sh_offset); if (err != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "load_modmetadata: unable to load set_modmetadata_set: %d\n", err); @@ -977,7 +1015,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest) dest += sh_meta->sh_size; /* Load data sections into memory. */ - err = kern_pread(ef.fd, dest, sh_data[0]->sh_size, + err = kern_pread(VECTX_HANDLE(&ef), dest, sh_data[0]->sh_size, sh_data[0]->sh_offset); if (err != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) @@ -992,7 +1030,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest) ef.off = -(sh_data[0]->sh_addr - dest); dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr); - err = kern_pread(ef.fd, dest, sh_data[1]->sh_size, + err = kern_pread(VECTX_HANDLE(&ef), dest, sh_data[1]->sh_size, sh_data[1]->sh_offset); if (err != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) @@ -1014,8 +1052,20 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest) free(shdr); if (ef.firstpage != NULL) free(ef.firstpage); - if (ef.fd != -1) + if (ef.fd != -1) { +#ifdef LOADER_VERIEXEC_VECTX + if (!err && ef.vctx) { + int verror; + + verror = vectx_close(ef.vctx, VE_MUST, __func__); + if (verror) { + err = EAUTH; + file_discard(fp); + } + } +#endif close(ef.fd); + } return (err); } diff --git a/stand/common/load_elf_obj.c b/stand/common/load_elf_obj.c index ae45ce7366b..4bff7476492 100644 --- a/stand/common/load_elf_obj.c +++ b/stand/common/load_elf_obj.c @@ -60,8 +60,17 @@ typedef struct elf_file { int fd; vm_offset_t off; +#ifdef LOADER_VERIEXEC_VECTX + struct vectx *vctx; +#endif } *elf_file_t; +#ifdef LOADER_VERIEXEC_VECTX +#define VECTX_HANDLE(ef) (ef)->vctx +#else +#define VECTX_HANDLE(ef) (ef)->fd +#endif + static int __elfN(obj_loadimage)(struct preloaded_file *mp, elf_file_t ef, uint64_t loadaddr); static int __elfN(obj_lookup_set)(struct preloaded_file *mp, elf_file_t ef, @@ -100,9 +109,22 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest, return(EFTYPE); if ((ef.fd = open(filename, O_RDONLY)) == -1) return(errno); +#ifdef LOADER_VERIEXEC_VECTX + { + int verror; + + ef.vctx = vectx_open(ef.fd, filename, 0L, NULL, &verror, __func__); + if (verror) { + printf("Unverified %s: %s\n", filename, ve_error_get()); + close(ef.fd); + free(ef.vctx); + return (EAUTH); + } + } +#endif hdr = &ef.hdr; - bytes_read = read(ef.fd, hdr, sizeof(*hdr)); + bytes_read = VECTX_READ(VECTX_HANDLE(&ef), hdr, sizeof(*hdr)); if (bytes_read != sizeof(*hdr)) { err = EFTYPE; /* could be EIO, but may be small file */ goto oerr; @@ -129,10 +151,10 @@ __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; +#if defined(LOADER_VERIEXEC) && !defined(LOADER_VERIEXEC_VECTX) + if (verify_file(ef.fd, filename, bytes_read, VE_MUST, __func__) < 0) { + err = EAUTH; + goto oerr; } #endif @@ -181,6 +203,17 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest, oerr: file_discard(fp); out: +#ifdef LOADER_VERIEXEC_VECTX + if (!err && ef.vctx) { + int verror; + + verror = vectx_close(ef.vctx, VE_MUST, __func__); + if (verror) { + err = EAUTH; + file_discard(fp); + } + } +#endif close(ef.fd); if (ef.e_shdr != NULL) free(ef.e_shdr); @@ -207,7 +240,7 @@ __elfN(obj_loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) /* Read in the section headers. */ shdrbytes = hdr->e_shnum * hdr->e_shentsize; - shdr = alloc_pread(ef->fd, (off_t)hdr->e_shoff, shdrbytes); + shdr = alloc_pread(VECTX_HANDLE(ef), (off_t)hdr->e_shoff, shdrbytes); if (shdr == NULL) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadimage: read section headers failed\n"); @@ -328,7 +361,7 @@ __elfN(obj_loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) if (cshdr == lshdr) break; - if (kern_pread(ef->fd, (vm_offset_t)cshdr->sh_addr, + if (kern_pread(VECTX_HANDLE(ef), (vm_offset_t)cshdr->sh_addr, cshdr->sh_size, (off_t)cshdr->sh_offset) != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadimage: read failed\n"); diff --git a/stand/common/misc.c b/stand/common/misc.c index 2ad9afaefa8..315cbe8ce3b 100644 --- a/stand/common/misc.c +++ b/stand/common/misc.c @@ -116,10 +116,10 @@ kern_bzero(vm_offset_t dest, size_t len) * and it just returns 0 if successful. */ int -kern_pread(int fd, vm_offset_t dest, size_t len, off_t off) +kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off) { - if (lseek(fd, off, SEEK_SET) == -1) { + if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) { #ifdef DEBUG printf("\nlseek failed\n"); #endif @@ -140,7 +140,7 @@ kern_pread(int fd, vm_offset_t dest, size_t len, off_t off) */ /* coverity[ -tainted_data_return ] */ void * -alloc_pread(int fd, off_t off, size_t len) +alloc_pread(readin_handle_t fd, off_t off, size_t len) { void *buf; @@ -151,14 +151,14 @@ alloc_pread(int fd, off_t off, size_t len) #endif return (NULL); } - if (lseek(fd, off, SEEK_SET) == -1) { + if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) { #ifdef DEBUG printf("\nlseek failed\n"); #endif free(buf); return (NULL); } - if ((size_t)read(fd, buf, len) != len) { + if ((size_t)VECTX_READ(fd, buf, len) != len) { #ifdef DEBUG printf("\nread failed\n"); #endif diff --git a/stand/common/module.c b/stand/common/module.c index 401bb884387..bd8d091d91c 100644 --- a/stand/common/module.c +++ b/stand/common/module.c @@ -616,6 +616,14 @@ file_load_dependencies(struct preloaded_file *base_file) return (error); } + +#ifdef LOADER_VERIEXEC_VECTX +#define VECTX_HANDLE(fd) vctx +#else +#define VECTX_HANDLE(fd) fd +#endif + + /* * We've been asked to load (fname) as (type), so just suck it in, * no arguments or anything. @@ -627,6 +635,10 @@ file_loadraw(const char *fname, char *type, int insert) char *name; int fd, got; vm_offset_t laddr; +#ifdef LOADER_VERIEXEC_VECTX + struct vectx *vctx; + int verror; +#endif /* We can't load first */ if ((file_findfile(NULL, NULL)) == NULL) { @@ -649,13 +661,26 @@ file_loadraw(const char *fname, char *type, int insert) return(NULL); } +#ifdef LOADER_VERIEXEC_VECTX + vctx = vectx_open(fd, name, 0L, NULL, &verror, __func__); + if (verror) { + sprintf(command_errbuf, "can't verify '%s': %s", + name, ve_error_get()); + free(name); + free(vctx); + close(fd); + return(NULL); + } +#else #ifdef LOADER_VERIEXEC - if (verify_file(fd, name, 0, VE_MUST) < 0) { - sprintf(command_errbuf, "can't verify '%s'", name); + if (verify_file(fd, name, 0, VE_MUST, __func__) < 0) { + sprintf(command_errbuf, "can't verify '%s': %s", + name, ve_error_get()); free(name); close(fd); return(NULL); } +#endif #endif if (archsw.arch_loadaddr != NULL) @@ -666,7 +691,7 @@ file_loadraw(const char *fname, char *type, int insert) laddr = loadaddr; for (;;) { /* read in 4k chunks; size is not really important */ - got = archsw.arch_readin(fd, laddr, 4096); + got = archsw.arch_readin(VECTX_HANDLE(fd), laddr, 4096); if (got == 0) /* end of file */ break; if (got < 0) { /* error */ @@ -674,12 +699,24 @@ file_loadraw(const char *fname, char *type, int insert) "error reading '%s': %s", name, strerror(errno)); free(name); close(fd); +#ifdef LOADER_VERIEXEC_VECTX + free(vctx); +#endif return(NULL); } laddr += got; } printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr)); +#ifdef LOADER_VERIEXEC_VECTX + verror = vectx_close(vctx, VE_MUST, __func__); + if (verror) { + free(name); + close(fd); + free(vctx); + return(NULL); + } +#endif /* Looks OK so far; create & populate control structure */ fp = file_alloc(); diff --git a/stand/common/readin.h b/stand/common/readin.h new file mode 100644 index 00000000000..72e2de8f608 --- /dev/null +++ b/stand/common/readin.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2020, Juniper Networks, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _READIN_H_ +#define _READIN_H_ + +#ifdef LOADER_VERIEXEC +#include +#endif +#ifdef LOADER_VERIEXEC_VECTX +typedef struct vectx * readin_handle_t; +#define VECTX_READ vectx_read +#define VECTX_LSEEK vectx_lseek +#else +typedef int readin_handle_t; +#define VECTX_READ read +#define VECTX_LSEEK lseek +#endif + +#endif /* !_READIN_H_ */ diff --git a/stand/efi/loader/arch/i386/i386_copy.c b/stand/efi/loader/arch/i386/i386_copy.c index 522913f5da4..2c4b0deb49c 100644 --- a/stand/efi/loader/arch/i386/i386_copy.c +++ b/stand/efi/loader/arch/i386/i386_copy.c @@ -51,9 +51,8 @@ i386_copyout(const vm_offset_t src, void *dest, const size_t len) return(len); } - ssize_t -i386_readin(const int fd, vm_offset_t dest, const size_t len) +i386_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) { - return (read(fd, PTOV(dest), len)); + return (VECTX_READ(fd, PTOV(dest), len)); } diff --git a/stand/efi/loader/copy.c b/stand/efi/loader/copy.c index d42c5e08ee4..914e406cc8b 100644 --- a/stand/efi/loader/copy.c +++ b/stand/efi/loader/copy.c @@ -280,14 +280,14 @@ efi_copyout(const vm_offset_t src, void *dest, const size_t len) ssize_t -efi_readin(const int fd, vm_offset_t dest, const size_t len) +efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) { if (dest + stage_offset + len > staging_end) { errno = ENOMEM; return (-1); } - return (read(fd, (void *)(dest + stage_offset), len)); + return (VECTX_READ(fd, (void *)(dest + stage_offset), len)); } void diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h index 780fbfe4c6a..4d077514e42 100644 --- a/stand/efi/loader/loader_efi.h +++ b/stand/efi/loader/loader_efi.h @@ -32,6 +32,7 @@ #define _LOADER_EFI_COPY_H_ #include +#include int efi_autoload(void); @@ -39,7 +40,7 @@ int efi_copy_init(void); ssize_t efi_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t efi_copyout(const vm_offset_t src, void *dest, const size_t len); -ssize_t efi_readin(const int fd, vm_offset_t dest, const size_t len); +ssize_t efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); void * efi_translate(vm_offset_t ptr); void efi_copy_finish(void); diff --git a/stand/efi/loader/main.c b/stand/efi/loader/main.c index 1701f218195..763a1d0771d 100644 --- a/stand/efi/loader/main.c +++ b/stand/efi/loader/main.c @@ -1454,6 +1454,14 @@ command_chain(int argc, char *argv[]) return (CMD_ERROR); } +#ifdef LOADER_VERIEXEC + if (verify_file(fd, name, 0, VE_MUST, __func__) < 0) { + sprintf(command_errbuf, "can't verify: %s", name); + close(fd); + return (CMD_ERROR); + } +#endif + if (fstat(fd, &st) < -1) { command_errmsg = "stat failed"; close(fd); diff --git a/stand/ficl/loader.c b/stand/ficl/loader.c index 6d25f5502d4..2d1e1b908e9 100644 --- a/stand/ficl/loader.c +++ b/stand/ficl/loader.c @@ -530,7 +530,7 @@ static void pfopen(FICL_VM *pVM) fd = open(name, mode); #ifdef LOADER_VERIEXEC if (fd >= 0) { - if (verify_file(fd, name, 0, VE_GUESS) < 0) { + if (verify_file(fd, name, 0, VE_GUESS, __func__) < 0) { /* not verified writing ok but reading is not */ if ((mode & O_ACCMODE) != O_WRONLY) { close(fd); diff --git a/stand/i386/libi386/i386_copy.c b/stand/i386/libi386/i386_copy.c index 3c05241985c..c46e2b11897 100644 --- a/stand/i386/libi386/i386_copy.c +++ b/stand/i386/libi386/i386_copy.c @@ -63,7 +63,7 @@ i386_copyout(const vm_offset_t src, void *dest, const size_t len) ssize_t -i386_readin(const int fd, vm_offset_t dest, const size_t len) +i386_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) { if (dest + len >= memtop_copyin) { @@ -71,5 +71,5 @@ i386_readin(const int fd, vm_offset_t dest, const size_t len) return(-1); } - return (read(fd, PTOV(dest), len)); + return (VECTX_READ(fd, PTOV(dest), len)); } diff --git a/stand/i386/libi386/libi386.h b/stand/i386/libi386/libi386.h index 2f254b918f5..d25df8fc44a 100644 --- a/stand/i386/libi386/libi386.h +++ b/stand/i386/libi386/libi386.h @@ -89,6 +89,8 @@ extern struct devdesc currdev; /* our current device */ #define MAXDEV 31 /* maximum number of distinct devices */ #define MAXBDDEV MAXDEV +#include + /* exported devices XXX rename? */ extern struct devsw bioscd; extern struct devsw biosfd; @@ -104,7 +106,7 @@ int bd_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */ ssize_t i386_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t i386_copyout(const vm_offset_t src, void *dest, const size_t len); -ssize_t i386_readin(const int fd, vm_offset_t dest, const size_t len); +ssize_t i386_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); struct preloaded_file; void bios_addsmapdata(struct preloaded_file *); diff --git a/stand/i386/loader/chain.c b/stand/i386/loader/chain.c index 43ba2697e93..d4e3936e13d 100644 --- a/stand/i386/loader/chain.c +++ b/stand/i386/loader/chain.c @@ -43,6 +43,12 @@ __FBSDID("$FreeBSD$"); #include "libi386/libi386.h" #include "btxv86.h" +#ifdef LOADER_VERIEXEC_VECTX +#define VECTX_HANDLE(x) vctx +#else +#define VECTX_HANDLE(x) x +#endif + /* * The MBR/VBR is located in first sector of disk/partition. * Read 512B to temporary location and set up relocation. Then @@ -59,6 +65,10 @@ command_chain(int argc, char *argv[]) struct stat st; vm_offset_t mem = 0x100000; struct i386_devdesc *rootdev; +#ifdef LOADER_VERIEXEC_VECTX + struct vectx *vctx; + int verror; +#endif if (argc == 1) { command_errmsg = "no device or file name specified"; @@ -75,6 +85,23 @@ command_chain(int argc, char *argv[]) return (CMD_ERROR); } +#ifdef LOADER_VERIEXEC_VECTX + vctx = vectx_open(fd, argv[1], 0L, NULL, &verror, __func__); + if (verror) { + sprintf(command_errbuf, "can't verify: %s", argv[1]); + close(fd); + free(vctx); + return (CMD_ERROR); + } +#else +#ifdef LOADER_VERIEXEC + if (verify_file(fd, argv[1], 0, VE_MUST, __func__) < 0) { + sprintf(command_errbuf, "can't verify: %s", argv[1]); + close(fd); + return (CMD_ERROR); + } +#endif +#endif len = strlen(argv[1]); if (argv[1][len-1] != ':') { if (fstat(fd, &st) == -1) { @@ -96,13 +123,19 @@ command_chain(int argc, char *argv[]) return (CMD_ERROR); } - if (archsw.arch_readin(fd, mem, size) != size) { + if (archsw.arch_readin(VECTX_HANDLE(fd), mem, size) != size) { command_errmsg = "failed to read disk"; close(fd); return (CMD_ERROR); } close(fd); - +#ifdef LOADER_VERIEXEC_VECTX + verror = vectx_close(vctx, VE_MUST, __func__); + if (verror) { + free(vctx); + return (CMD_ERROR); + } +#endif if (argv[1][len-1] == ':' && *((uint16_t *)PTOV(mem + DOSMAGICOFFSET)) != DOSMAGIC) { command_errmsg = "wrong magic"; diff --git a/stand/libsa/pkgfs.c b/stand/libsa/pkgfs.c index e78ba3302e1..df87a703515 100644 --- a/stand/libsa/pkgfs.c +++ b/stand/libsa/pkgfs.c @@ -46,6 +46,7 @@ static int pkg_read(struct open_file *, void *, size_t, size_t *); static off_t pkg_seek(struct open_file *, off_t, int); static int pkg_stat(struct open_file *, struct stat *); static int pkg_readdir(struct open_file *, struct dirent *); +static off_t pkg_atol(const char *, unsigned); struct fs_ops pkgfs_fsops = { "pkg", @@ -59,7 +60,7 @@ struct fs_ops pkgfs_fsops = { }; #define PKG_BUFSIZE 512 -#define PKG_MAXCACHESZ 4096 +#define PKG_MAXCACHESZ 16384 #define PKG_FILEEXT ".tgz" @@ -334,6 +335,7 @@ pkg_seek(struct open_file *f, off_t ofs, int whence) char buf[512]; struct tarfile *tf; off_t delta; + off_t nofs; size_t sz, res; int error; @@ -359,6 +361,14 @@ pkg_seek(struct open_file *f, off_t ofs, int whence) } if (delta < 0) { + /* seeking backwards - ok if within cache */ + if (tf->tf_cachesz > 0 && tf->tf_fp <= tf->tf_cachesz) { + nofs = tf->tf_fp + delta; + if (nofs >= 0) { + tf->tf_fp = nofs; + return (tf->tf_fp); + } + } DBG(("%s: negative file seek (%jd)\n", __func__, (intmax_t)delta)); errno = ESPIPE; @@ -388,8 +398,15 @@ pkg_stat(struct open_file *f, struct stat *sb) return (EBADF); memset(sb, 0, sizeof(*sb)); sb->st_mode = get_mode(tf); + if ((sb->st_mode & S_IFMT) == 0) { + /* tar file bug - assume regular file */ + sb->st_mode |= S_IFREG; + } sb->st_size = tf->tf_size; sb->st_blocks = (tf->tf_size + 511) / 512; + sb->st_mtime = pkg_atol(tf->tf_hdr.ut_mtime, 12); + sb->st_dev = (off_t)tf->tf_pkg; + sb->st_ino = tf->tf_ofs; /* unique per tf_pkg */ return (0); } diff --git a/stand/loader.mk b/stand/loader.mk index b1ca8df3d78..fc580f57899 100644 --- a/stand/loader.mk +++ b/stand/loader.mk @@ -76,6 +76,9 @@ SRCS+= interp_simple.c .if ${MK_LOADER_VERIEXEC} != "no" CFLAGS+= -DLOADER_VERIEXEC -I${SRCTOP}/lib/libsecureboot/h +.if ${MK_LOADER_VERIEXEC_VECTX} != "no" +CFLAGS+= -DLOADER_VERIEXEC_VECTX +.endif .endif .if ${MK_LOADER_VERIEXEC_PASS_MANIFEST} != "no" diff --git a/stand/mips/beri/loader/arch.c b/stand/mips/beri/loader/arch.c index 5ce8ede9c6a..a30f18dfbce 100644 --- a/stand/mips/beri/loader/arch.c +++ b/stand/mips/beri/loader/arch.c @@ -44,7 +44,7 @@ static int beri_arch_autoload(void); static ssize_t beri_arch_copyin(const void *src, vm_offset_t va, size_t len); static ssize_t beri_arch_copyout(vm_offset_t va, void *dst, size_t len); static uint64_t beri_arch_loadaddr(u_int type, void *data, uint64_t addr); -static ssize_t beri_arch_readin(int fd, vm_offset_t va, size_t len); +static ssize_t beri_arch_readin(readin_handle_t fd, vm_offset_t va, size_t len); struct arch_switch archsw = { .arch_autoload = beri_arch_autoload, @@ -90,8 +90,8 @@ beri_arch_loadaddr(u_int type, void *data, uint64_t addr) } static ssize_t -beri_arch_readin(int fd, vm_offset_t va, size_t len) +beri_arch_readin(readin_handle_t fd, vm_offset_t va, size_t len) { - return (read(fd, (void *)va, len)); + return (VECTX_READ(fd, (void *)va, len)); } diff --git a/stand/powerpc/kboot/main.c b/stand/powerpc/kboot/main.c index 25eaf506448..8b360ecaa26 100644 --- a/stand/powerpc/kboot/main.c +++ b/stand/powerpc/kboot/main.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$"); #define _KERNEL #include -#include "bootstrap.h" +#include #include "host_syscall.h" @@ -43,7 +43,7 @@ extern void *_end; int kboot_getdev(void **vdev, const char *devspec, const char **path); ssize_t kboot_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t kboot_copyout(vm_offset_t src, void *dest, const size_t len); -ssize_t kboot_readin(const int fd, vm_offset_t dest, const size_t len); +ssize_t kboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); int kboot_autoload(void); uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr); int kboot_setcurrdev(struct env_var *ev, int flags, const void *value); @@ -411,7 +411,7 @@ kboot_copyout(vm_offset_t src, void *dest, const size_t len) } ssize_t -kboot_readin(const int fd, vm_offset_t dest, const size_t len) +kboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) { void *buf; size_t resid, chunk, get; @@ -429,7 +429,7 @@ kboot_readin(const int fd, vm_offset_t dest, const size_t len) for (resid = len; resid > 0; resid -= got, p += got) { get = min(chunk, resid); - got = read(fd, buf, get); + got = VECTX_READ(fd, buf, get); if (got <= 0) { if (got < 0) printf("kboot_readin: read failed\n"); diff --git a/stand/uboot/lib/copy.c b/stand/uboot/lib/copy.c index 7fd5fd671c0..65451d0fbec 100644 --- a/stand/uboot/lib/copy.c +++ b/stand/uboot/lib/copy.c @@ -160,7 +160,7 @@ uboot_copyout(const vm_offset_t src, void *dest, const size_t len) } ssize_t -uboot_readin(const int fd, vm_offset_t dest, const size_t len) +uboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len) { - return (read(fd, (void *)dest, len)); + return (VECTX_READ(fd, (void *)dest, len)); } diff --git a/stand/uboot/lib/libuboot.h b/stand/uboot/lib/libuboot.h index 59438e711a6..18a12c216d7 100644 --- a/stand/uboot/lib/libuboot.h +++ b/stand/uboot/lib/libuboot.h @@ -28,6 +28,7 @@ */ #include +#include struct uboot_devdesc { union { @@ -62,7 +63,7 @@ extern uintptr_t uboot_heap_end; uint64_t uboot_loadaddr(u_int type, void *data, uint64_t addr); ssize_t uboot_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t uboot_copyout(const vm_offset_t src, void *dest, const size_t len); -ssize_t uboot_readin(const int fd, vm_offset_t dest, const size_t len); +ssize_t uboot_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); extern int uboot_autoload(void); struct preloaded_file; diff --git a/stand/userboot/test/test.c b/stand/userboot/test/test.c index 5efe1d3784d..f2fee82663d 100644 --- a/stand/userboot/test/test.c +++ b/stand/userboot/test/test.c @@ -223,15 +223,20 @@ test_seek(void *arg, void *h, uint64_t offset, int whence) } int -test_stat(void *arg, void *h, int *mode_return, int *uid_return, int *gid_return, - uint64_t *size_return) +test_stat(void *arg, void *h, struct stat *stp) { struct test_file *tf = h; - *mode_return = tf->tf_stat.st_mode; - *uid_return = tf->tf_stat.st_uid; - *gid_return = tf->tf_stat.st_gid; - *size_return = tf->tf_stat.st_size; + if (!stp) + return (-1); + memset(stp, 0, sizeof(struct stat)); + stp->st_mode = tf->tf_stat.st_mode; + stp->st_uid = tf->tf_stat.st_uid; + stp->st_gid = tf->tf_stat.st_gid; + stp->st_size = tf->tf_stat.st_size; + stp->st_ino = tf->tf_stat.st_ino; + stp->st_dev = tf->tf_stat.st_dev; + stp->st_mtime = tf->tf_stat.st_mtime; return (0); } diff --git a/stand/userboot/userboot.h b/stand/userboot/userboot.h index e8817aeb39a..de0cdb6605c 100644 --- a/stand/userboot/userboot.h +++ b/stand/userboot/userboot.h @@ -119,8 +119,7 @@ struct loader_callbacks { /* * Return some stat(2) related information about the file */ - int (*stat)(void *arg, void *h, int *mode_return, - int *uid_return, int *gid_return, uint64_t *size_return); + int (*stat)(void *arg, void *h, struct stat *stp); /* * Disk image i/o diff --git a/stand/userboot/userboot/conf.c b/stand/userboot/userboot/conf.c index 3a4417f576a..af63528163d 100644 --- a/stand/userboot/userboot/conf.c +++ b/stand/userboot/userboot/conf.c @@ -73,6 +73,11 @@ struct fs_ops *file_system[] = { NULL }; +/* to keep libsa happy */ +struct netif_driver *netif_drivers[] = { + NULL +}; + /* Exported for i386 only */ /* * Sort formats so that those that can detect based on arguments diff --git a/stand/userboot/userboot/copy.c b/stand/userboot/userboot/copy.c index f8763e9b526..f39c83c57d7 100644 --- a/stand/userboot/userboot/copy.c +++ b/stand/userboot/userboot/copy.c @@ -48,7 +48,7 @@ userboot_copyout(vm_offset_t va, void *dst, size_t len) } ssize_t -userboot_readin(int fd, vm_offset_t va, size_t len) +userboot_readin(readin_handle_t fd, vm_offset_t va, size_t len) { ssize_t res, s; size_t sz; @@ -59,7 +59,7 @@ userboot_readin(int fd, vm_offset_t va, size_t len) sz = len; if (sz > sizeof(buf)) sz = sizeof(buf); - s = read(fd, buf, sz); + s = VECTX_READ(fd, buf, sz); if (s == 0) break; if (s < 0) diff --git a/stand/userboot/userboot/host.c b/stand/userboot/userboot/host.c index 861856544aa..c9ac01576e8 100644 --- a/stand/userboot/userboot/host.c +++ b/stand/userboot/userboot/host.c @@ -84,16 +84,8 @@ host_seek(struct open_file *f, off_t offset, int where) static int host_stat(struct open_file *f, struct stat *sb) { - int mode; - int uid; - int gid; - uint64_t size; - - CALLBACK(stat, f->f_fsdata, &mode, &uid, &gid, &size); - sb->st_mode = mode; - sb->st_uid = uid; - sb->st_gid = gid; - sb->st_size = size; + + CALLBACK(stat, f->f_fsdata, sb); return (0); } diff --git a/stand/userboot/userboot/libuserboot.h b/stand/userboot/userboot/libuserboot.h index e2048d5fef9..fa60180c6b0 100644 --- a/stand/userboot/userboot/libuserboot.h +++ b/stand/userboot/userboot/libuserboot.h @@ -27,6 +27,7 @@ */ #include "userboot.h" +#include extern struct loader_callbacks *callbacks; extern void *callbacks_arg; @@ -54,7 +55,7 @@ extern void delay(int); extern int userboot_autoload(void); extern ssize_t userboot_copyin(const void *, vm_offset_t, size_t); extern ssize_t userboot_copyout(vm_offset_t, void *, size_t); -extern ssize_t userboot_readin(int, vm_offset_t, size_t); +extern ssize_t userboot_readin(readin_handle_t, vm_offset_t, size_t); extern int userboot_getdev(void **, const char *, const char **); char *userboot_fmtdev(void *vdev); int userboot_setcurrdev(struct env_var *ev, int flags, const void *value); diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c index 5ce75f96bea..6db41a49853 100644 --- a/usr.sbin/bhyveload/bhyveload.c +++ b/usr.sbin/bhyveload/bhyveload.c @@ -278,14 +278,19 @@ cb_seek(void *arg, void *h, uint64_t offset, int whence) } static int -cb_stat(void *arg, void *h, int *mode, int *uid, int *gid, uint64_t *size) +cb_stat(void *arg, void *h, struct stat *sbp) { struct cb_file *cf = h; - *mode = cf->cf_stat.st_mode; - *uid = cf->cf_stat.st_uid; - *gid = cf->cf_stat.st_gid; - *size = cf->cf_stat.st_size; + memset(sbp, 0, sizeof(struct stat)); + sbp->st_mode = cf->cf_stat.st_mode; + sbp->st_uid = cf->cf_stat.st_uid; + sbp->st_gid = cf->cf_stat.st_gid; + sbp->st_size = cf->cf_stat.st_size; + sbp->st_mtime = cf->cf_stat.st_mtime; + sbp->st_dev = cf->cf_stat.st_dev; + sbp->st_ino = cf->cf_stat.st_ino; + return (0); } -- 2.45.0