summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2020-04-09 04:50:19 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2020-04-09 04:50:19 +0000
commit19815ded6503c7e91e54f20f67ba16f72f74fe52 (patch)
tree065897a8ed97122e7b68afe3862fe4e9db1cc981
parentaaca66d865528ac532557ffd4aeae9417da4ee0d (diff)
downloadsrc-test2-19815ded6503c7e91e54f20f67ba16f72f74fe52.tar.gz
src-test2-19815ded6503c7e91e54f20f67ba16f72f74fe52.zip
Notes
-rw-r--r--lib/libsecureboot/h/libsecureboot.h9
-rw-r--r--lib/libsecureboot/h/verify_file.h24
-rw-r--r--lib/libsecureboot/tests/tvo.c20
-rw-r--r--lib/libsecureboot/vectx.c112
-rw-r--r--lib/libsecureboot/veopen.c8
-rw-r--r--lib/libsecureboot/vepcr.c79
-rw-r--r--lib/libsecureboot/verify_file.c141
-rw-r--r--lib/libsecureboot/vets.c23
-rw-r--r--share/mk/src.opts.mk1
-rw-r--r--stand/common/bootstrap.h12
-rw-r--r--stand/common/install.c11
-rw-r--r--stand/common/interp_forth.c4
-rw-r--r--stand/common/interp_simple.c2
-rw-r--r--stand/common/load_elf.c86
-rw-r--r--stand/common/load_elf_obj.c47
-rw-r--r--stand/common/misc.c10
-rw-r--r--stand/common/module.c43
-rw-r--r--stand/common/readin.h43
-rw-r--r--stand/efi/loader/arch/i386/i386_copy.c5
-rw-r--r--stand/efi/loader/copy.c4
-rw-r--r--stand/efi/loader/loader_efi.h3
-rw-r--r--stand/efi/loader/main.c8
-rw-r--r--stand/ficl/loader.c2
-rw-r--r--stand/i386/libi386/i386_copy.c4
-rw-r--r--stand/i386/libi386/libi386.h4
-rw-r--r--stand/i386/loader/chain.c37
-rw-r--r--stand/libsa/pkgfs.c19
-rw-r--r--stand/loader.mk3
-rw-r--r--stand/mips/beri/loader/arch.c6
-rw-r--r--stand/powerpc/kboot/main.c8
-rw-r--r--stand/uboot/lib/copy.c4
-rw-r--r--stand/uboot/lib/libuboot.h3
-rw-r--r--stand/userboot/test/test.c17
-rw-r--r--stand/userboot/userboot.h3
-rw-r--r--stand/userboot/userboot/conf.c5
-rw-r--r--stand/userboot/userboot/copy.c4
-rw-r--r--stand/userboot/userboot/host.c12
-rw-r--r--stand/userboot/userboot/libuserboot.h3
-rw-r--r--usr.sbin/bhyveload/bhyveload.c15
39 files changed, 654 insertions, 190 deletions
diff --git a/lib/libsecureboot/h/libsecureboot.h b/lib/libsecureboot/h/libsecureboot.h
index d7d72e880744..33f98bca0479 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 c10f17af1469..844b8266f42c 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 ad3bccb0614f..879d87f128f1 100644
--- a/lib/libsecureboot/tests/tvo.c
+++ b/lib/libsecureboot/tests/tvo.c
@@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <verify_file.h>
+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 97a8d97efb88..433df00f244c 100644
--- a/lib/libsecureboot/vectx.c
+++ b/lib/libsecureboot/vectx.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#endif
#include "libsecureboot-priv.h"
+#include <verify_file.h>
/**
* @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 @@ enomem: /* unlikely */
*
* 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 6ecf85c44af1..da6291504c4c 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 a97cb7245832..88128647b086 100644
--- a/lib/libsecureboot/vepcr.c
+++ b/lib/libsecureboot/vepcr.c
@@ -25,6 +25,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/queue.h>
#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 92845fb6879d..20fc0ae4ae78 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);
@@ -392,6 +441,12 @@ verify_file(int fd, const char *filename, off_t off, int severity)
*/
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) {
#if defined(VE_DEBUG_LEVEL) && VE_DEBUG_LEVEL > 0
@@ -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 c4d34ec6d4f5..3a82592ea699 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 6f06e07f9456..c04a7bdc219e 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 3e723765104e..2be6538efe4c 100644
--- a/stand/common/bootstrap.h
+++ b/stand/common/bootstrap.h
@@ -33,6 +33,8 @@
#include <sys/queue.h>
#include <sys/linker_set.h>
+#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 <verify_file.h>
-#endif
-
#endif /* !_BOOTSTRAP_H_ */
diff --git a/stand/common/install.c b/stand/common/install.c
index 0ba73e491b68..032006ec4fd3 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 04b94ff20a15..19f1c75dc191 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 80d756f9dfeb..e25743d4f01c 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 6b3ed719f7b2..7139dc8b7c32 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 @@ error:
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 @@ oerr:
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 @@ out:
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 ae45ce7366b7..4bff74764922 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 @@ ioerr:
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 2ad9afaefa87..315cbe8ce3bf 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 401bb8843874..bd8d091d91c9 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,14 +661,27 @@ 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)
loadaddr = archsw.arch_loadaddr(LOAD_RAW, name, loadaddr);
@@ -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 000000000000..72e2de8f6087
--- /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 <verify_file.h>
+#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 522913f5da43..2c4b0deb49cf 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 d42c5e08ee48..914e406cc8b5 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 780fbfe4c6aa..4d077514e423 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 <stand.h>
+#include <readin.h>
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 1701f2181953..763a1d0771d0 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 6d25f5502d49..2d1e1b908e9d 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 3c05241985c8..c46e2b118976 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 2f254b918f5c..d25df8fc44a5 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 <readin.h>
+
/* 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 43ba2697e938..d4e3936e13df 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 e78ba3302e1f..df87a7035153 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 b1ca8df3d78e..fc580f578997 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 5ce8ede9c6a3..a30f18dfbce9 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 25eaf5064489..8b360ecaa263 100644
--- a/stand/powerpc/kboot/main.c
+++ b/stand/powerpc/kboot/main.c
@@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
#define _KERNEL
#include <machine/cpufunc.h>
-#include "bootstrap.h"
+#include <bootstrap.h>
#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 7fd5fd671c02..65451d0fbec0 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 59438e711a65..18a12c216d7e 100644
--- a/stand/uboot/lib/libuboot.h
+++ b/stand/uboot/lib/libuboot.h
@@ -28,6 +28,7 @@
*/
#include <disk.h>
+#include <readin.h>
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 5efe1d3784de..f2fee82663d6 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 e8817aeb39a2..de0cdb6605c8 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 3a4417f576a4..af63528163d5 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 f8763e9b526a..f39c83c57d70 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 861856544aa2..c9ac01576e82 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 e2048d5fef94..fa60180c6b08 100644
--- a/stand/userboot/userboot/libuserboot.h
+++ b/stand/userboot/userboot/libuserboot.h
@@ -27,6 +27,7 @@
*/
#include "userboot.h"
+#include <readin.h>
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 5ce75f96bea4..6db41a498534 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);
}