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. Reviewed by: imp,tsoome MFC after: 1 week Sponsored by: Juniper Networks Differential Revision: https://reviews.freebsd.org//D23827
This commit is contained in:
parent
601ee53858
commit
afc571b1a6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=358744
@ -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 *,
|
int ve_check_hash(br_hash_compat_context *, const br_hash_class *,
|
||||||
const char *, const char *, size_t);
|
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);
|
char * hexdigest(char *, size_t, unsigned char *, size_t);
|
||||||
int verify_fd(int, const char *, off_t, struct stat *);
|
int verify_fd(int, const char *, off_t, struct stat *);
|
||||||
int verify_open(const char *, int);
|
int verify_open(const char *, int);
|
||||||
|
@ -39,13 +39,21 @@
|
|||||||
|
|
||||||
struct stat;
|
struct stat;
|
||||||
|
|
||||||
|
int verify_prep(int, const char *, off_t, struct stat *, const char *);
|
||||||
void ve_debug_set(int);
|
void ve_debug_set(int);
|
||||||
int ve_status_get(int);
|
char *ve_error_get(void);
|
||||||
void ve_efi_init(void);
|
void ve_efi_init(void);
|
||||||
|
int ve_status_get(int);
|
||||||
int load_manifest(const char *, const char *, const char *, struct stat *);
|
int load_manifest(const char *, const char *, const char *, struct stat *);
|
||||||
int pass_manifest(const char *, const char *);
|
int pass_manifest(const char *, const char *);
|
||||||
int pass_manifest_export_envs(void);
|
int pass_manifest_export_envs(void);
|
||||||
int verify_file(int, const char *, off_t, int);
|
int verify_file(int, const char *, off_t, int, const char *);
|
||||||
void verify_pcr_export(void);
|
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_ */
|
#endif /* _VERIFY_FILE_H_ */
|
||||||
|
@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <verify_file.h>
|
#include <verify_file.h>
|
||||||
|
|
||||||
|
size_t DestdirLen;
|
||||||
|
char *Destdir;
|
||||||
char *Skip;
|
char *Skip;
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -42,7 +44,10 @@ main(int argc, char *argv[])
|
|||||||
int Vflag;
|
int Vflag;
|
||||||
char *cp;
|
char *cp;
|
||||||
char *prefix;
|
char *prefix;
|
||||||
|
char *destdir;
|
||||||
|
|
||||||
|
Destdir = NULL;
|
||||||
|
DestdirLen = 0;
|
||||||
prefix = NULL;
|
prefix = NULL;
|
||||||
Skip = NULL;
|
Skip = NULL;
|
||||||
|
|
||||||
@ -50,8 +55,12 @@ main(int argc, char *argv[])
|
|||||||
printf("Trust %d\n", n);
|
printf("Trust %d\n", n);
|
||||||
Vflag = 0;
|
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) {
|
switch (c) {
|
||||||
|
case 'D':
|
||||||
|
Destdir = optarg;
|
||||||
|
DestdirLen = strlen(optarg);
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
DebugVe++;
|
DebugVe++;
|
||||||
break;
|
break;
|
||||||
@ -92,7 +101,7 @@ main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
int x;
|
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);
|
printf("verify_file(%s) = %d\n", argv[optind], x);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@ -147,7 +156,7 @@ main(int argc, char *argv[])
|
|||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
off = st.st_size % 512;
|
off = st.st_size % 512;
|
||||||
vp = vectx_open(fd, argv[optind], off,
|
vp = vectx_open(fd, argv[optind], off,
|
||||||
&st, &error);
|
&st, &error, __func__);
|
||||||
if (!vp) {
|
if (!vp) {
|
||||||
printf("vectx_open(%s) failed: %d %s\n",
|
printf("vectx_open(%s) failed: %d %s\n",
|
||||||
argv[optind], error,
|
argv[optind], error,
|
||||||
@ -155,7 +164,8 @@ main(int argc, char *argv[])
|
|||||||
} else {
|
} else {
|
||||||
off = vectx_lseek(vp,
|
off = vectx_lseek(vp,
|
||||||
(st.st_size % 1024), SEEK_SET);
|
(st.st_size % 1024), SEEK_SET);
|
||||||
|
/* we can seek backwards! */
|
||||||
|
off = vectx_lseek(vp, off/2, SEEK_SET);
|
||||||
if (off < st.st_size) {
|
if (off < st.st_size) {
|
||||||
n = vectx_read(vp, buf,
|
n = vectx_read(vp, buf,
|
||||||
sizeof(buf));
|
sizeof(buf));
|
||||||
@ -165,7 +175,7 @@ main(int argc, char *argv[])
|
|||||||
off = vectx_lseek(vp, 0, SEEK_END);
|
off = vectx_lseek(vp, 0, SEEK_END);
|
||||||
/* repeating that should be harmless */
|
/* repeating that should be harmless */
|
||||||
off = vectx_lseek(vp, 0, SEEK_END);
|
off = vectx_lseek(vp, 0, SEEK_END);
|
||||||
error = vectx_close(vp);
|
error = vectx_close(vp, VE_MUST, __func__);
|
||||||
if (error) {
|
if (error) {
|
||||||
printf("vectx_close(%s) == %d %s\n",
|
printf("vectx_close(%s) == %d %s\n",
|
||||||
argv[optind], error,
|
argv[optind], error,
|
||||||
|
@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "libsecureboot-priv.h"
|
#include "libsecureboot-priv.h"
|
||||||
|
#include <verify_file.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file vectx.c
|
* @file vectx.c
|
||||||
@ -50,12 +51,14 @@ struct vectx {
|
|||||||
const char *vec_path; /* path we are verifying */
|
const char *vec_path; /* path we are verifying */
|
||||||
const char *vec_want; /* hash value we want */
|
const char *vec_want; /* hash value we want */
|
||||||
off_t vec_off; /* current offset */
|
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_size; /* size of path */
|
||||||
size_t vec_hashsz; /* size of hash */
|
size_t vec_hashsz; /* size of hash */
|
||||||
int vec_fd; /* file descriptor */
|
int vec_fd; /* file descriptor */
|
||||||
int vec_status; /* verification status */
|
int vec_status; /* verification status */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* verify an open file as we read it
|
* 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.
|
* NULL is only returned for non-files or out-of-memory.
|
||||||
*/
|
*/
|
||||||
struct vectx *
|
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 vectx *ctx;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
size_t hashsz;
|
size_t hashsz;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!stp) {
|
if (!stp)
|
||||||
if (fstat(fd, &st) == 0)
|
|
||||||
stp = &st;
|
stp = &st;
|
||||||
}
|
|
||||||
|
|
||||||
/* we *should* only get called for files */
|
rc = verify_prep(fd, path, off, stp, __func__);
|
||||||
if (stp && !S_ISREG(stp->st_mode)) {
|
|
||||||
*error = 0;
|
DEBUG_PRINTF(2,
|
||||||
|
("vectx_open: caller=%s,name='%s',prep_rc=%d\n",
|
||||||
|
caller,path, rc));
|
||||||
|
|
||||||
|
switch (rc) {
|
||||||
|
case VE_FINGERPRINT_NONE:
|
||||||
|
case VE_FINGERPRINT_UNKNOWN:
|
||||||
|
case VE_FINGERPRINT_WRONG:
|
||||||
|
*error = rc;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = malloc(sizeof(struct vectx));
|
ctx = malloc(sizeof(struct vectx));
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
goto enomem;
|
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_path = path;
|
||||||
ctx->vec_size = stp->st_size;
|
ctx->vec_size = stp->st_size;
|
||||||
ctx->vec_off = 0;
|
ctx->vec_off = 0;
|
||||||
|
ctx->vec_hashed = 0;
|
||||||
ctx->vec_want = NULL;
|
ctx->vec_want = NULL;
|
||||||
ctx->vec_status = 0;
|
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);
|
cp = fingerprint_info_lookup(fd, path);
|
||||||
if (!cp) {
|
if (!cp) {
|
||||||
ctx->vec_status = VE_FINGERPRINT_NONE;
|
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);
|
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);
|
return (ctx);
|
||||||
|
|
||||||
enomem: /* unlikely */
|
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.
|
* It is critical that all file I/O comes through here.
|
||||||
* We keep track of current offset.
|
* 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
|
* @param[in] pctx
|
||||||
* pointer to ctx
|
* pointer to ctx
|
||||||
@ -190,6 +212,8 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
|
|||||||
{
|
{
|
||||||
unsigned char *bp = buf;
|
unsigned char *bp = buf;
|
||||||
int n;
|
int n;
|
||||||
|
int delta;
|
||||||
|
int x;
|
||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
if (ctx->vec_hashsz == 0) /* nothing to do */
|
if (ctx->vec_hashsz == 0) /* nothing to do */
|
||||||
@ -200,10 +224,21 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
|
|||||||
n = read(ctx->vec_fd, &bp[off], nbytes - off);
|
n = read(ctx->vec_fd, &bp[off], nbytes - off);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return (n);
|
return (n);
|
||||||
|
if (n > 0) {
|
||||||
|
/* 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) {
|
if (n > 0) {
|
||||||
ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], n);
|
ctx->vec_md->update(&ctx->vec_ctx.vtable, &bp[off], n);
|
||||||
off += n;
|
off += n;
|
||||||
ctx->vec_off += n;
|
ctx->vec_off += n;
|
||||||
|
ctx->vec_hashed += n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (n > 0 && off < nbytes);
|
} while (n > 0 && off < nbytes);
|
||||||
return (off);
|
return (off);
|
||||||
@ -213,10 +248,10 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
|
|||||||
* @brief
|
* @brief
|
||||||
* vectx equivalent of lseek
|
* 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.
|
* to reach the desired offset.
|
||||||
*
|
*
|
||||||
* We do not support seeking backwards.
|
* We support seeking backwards.
|
||||||
*
|
*
|
||||||
* @param[in] pctx
|
* @param[in] pctx
|
||||||
* pointer to ctx
|
* pointer to ctx
|
||||||
@ -225,6 +260,8 @@ vectx_read(struct vectx *ctx, void *buf, size_t nbytes)
|
|||||||
* desired offset
|
* desired offset
|
||||||
*
|
*
|
||||||
* @param[in] whence
|
* @param[in] whence
|
||||||
|
* We try to convert whence to ``SEEK_SET``.
|
||||||
|
* We do not support ``SEEK_DATA`` or ``SEEK_HOLE``.
|
||||||
*
|
*
|
||||||
* @return offset or error.
|
* @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));
|
return (lseek(ctx->vec_fd, off, whence));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to convert whence to SEEK_SET
|
* Convert whence to SEEK_SET
|
||||||
* but we cannot support seeking backwards!
|
|
||||||
* Nor beyond end of file.
|
|
||||||
*/
|
*/
|
||||||
if (whence == SEEK_END && off <= 0) {
|
if (whence == SEEK_END && off <= 0) {
|
||||||
whence = SEEK_SET;
|
whence = SEEK_SET;
|
||||||
off += ctx->vec_size;
|
off += ctx->vec_size;
|
||||||
} else if (whence == SEEK_CUR && off >= 0) {
|
} else if (whence == SEEK_CUR) {
|
||||||
whence = SEEK_SET;
|
whence = SEEK_SET;
|
||||||
off += ctx->vec_off;
|
off += ctx->vec_off;
|
||||||
}
|
}
|
||||||
if (whence != SEEK_SET || off < ctx->vec_off ||
|
if (whence != SEEK_SET ||
|
||||||
(size_t)off > ctx->vec_size) {
|
(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);
|
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;
|
n = 0;
|
||||||
do {
|
do {
|
||||||
delta = off - ctx->vec_off;
|
delta = off - ctx->vec_off;
|
||||||
@ -281,16 +322,35 @@ vectx_lseek(struct vectx *ctx, off_t off, int whence)
|
|||||||
* @return 0 or an error.
|
* @return 0 or an error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vectx_close(struct vectx *ctx)
|
vectx_close(struct vectx *ctx, int severity, const char *caller)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (ctx->vec_hashsz == 0) {
|
if (ctx->vec_hashsz == 0) {
|
||||||
rc = ctx->vec_status;
|
rc = ctx->vec_status;
|
||||||
} else {
|
} 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
|
||||||
rc = ve_check_hash(&ctx->vec_ctx, ctx->vec_md,
|
rc = ve_check_hash(&ctx->vec_ctx, ctx->vec_md,
|
||||||
ctx->vec_path, ctx->vec_want, ctx->vec_hashsz);
|
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 (severity > VE_WANT || rc == VE_FINGERPRINT_WRONG)
|
||||||
|
printf("%serified %s\n", (rc <= 0) ? "Unv" : "V",
|
||||||
|
ctx->vec_path);
|
||||||
|
#if !defined(UNIT_TEST) && !defined(DEBUG_VECTX)
|
||||||
|
/* we are generally called with VE_MUST */
|
||||||
|
if (severity > VE_WANT && rc == VE_FINGERPRINT_WRONG)
|
||||||
|
panic("cannot continue");
|
||||||
|
#endif
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return ((rc < 0) ? rc : 0);
|
return ((rc < 0) ? rc : 0);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
* define MANIFEST_SKIP to Skip - in tests/tvo.c so that
|
* define MANIFEST_SKIP to Skip - in tests/tvo.c so that
|
||||||
* tvo can control the value we use in find_manifest()
|
* tvo can control the value we use in find_manifest()
|
||||||
*/
|
*/
|
||||||
|
extern char *Destdir;
|
||||||
|
extern size_t DestdirLen;
|
||||||
extern char *Skip;
|
extern char *Skip;
|
||||||
# undef MANIFEST_SKIP
|
# undef MANIFEST_SKIP
|
||||||
# define MANIFEST_SKIP Skip
|
# define MANIFEST_SKIP Skip
|
||||||
@ -167,12 +169,21 @@ load_manifest(const char *name, const char *prefix,
|
|||||||
ve_utc_set(stp->st_mtime);
|
ve_utc_set(stp->st_mtime);
|
||||||
content = (char *)verify_signed(name, VEF_VERBOSE);
|
content = (char *)verify_signed(name, VEF_VERBOSE);
|
||||||
if (content) {
|
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);
|
fingerprint_info_add(name, prefix, skip, content, stp);
|
||||||
add_verify_status(stp, VE_VERIFIED);
|
add_verify_status(stp, VE_VERIFIED);
|
||||||
loaded_manifests = 1; /* we are verifying! */
|
loaded_manifests = 1; /* we are verifying! */
|
||||||
DEBUG_PRINTF(3, ("loaded: %s %s %s\n",
|
DEBUG_PRINTF(3, ("loaded: %s %s %s\n",
|
||||||
name, prefix, skip));
|
name, prefix, skip));
|
||||||
rc = 0;
|
rc = VE_VERIFIED;
|
||||||
} else {
|
} else {
|
||||||
rc = VE_FINGERPRINT_WRONG;
|
rc = VE_FINGERPRINT_WRONG;
|
||||||
add_verify_status(stp, rc); /* remember */
|
add_verify_status(stp, rc); /* remember */
|
||||||
@ -245,13 +256,15 @@ severity_guess(const char *filename)
|
|||||||
return (VE_WANT);
|
return (VE_WANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int Verifying = -1; /* 0 if not verifying */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
verify_tweak(int fd, off_t off, struct stat *stp,
|
verify_tweak(int fd, off_t off, struct stat *stp,
|
||||||
char *tweak, int *accept_no_fp,
|
char *tweak, int *accept_no_fp,
|
||||||
int *verbose, int *verifying)
|
int *verbose)
|
||||||
{
|
{
|
||||||
if (strcmp(tweak, "off") == 0) {
|
if (strcmp(tweak, "off") == 0) {
|
||||||
*verifying = 0;
|
Verifying = 0;
|
||||||
} else if (strcmp(tweak, "strict") == 0) {
|
} else if (strcmp(tweak, "strict") == 0) {
|
||||||
/* anything caller wants verified must be */
|
/* anything caller wants verified must be */
|
||||||
*accept_no_fp = VE_WANT;
|
*accept_no_fp = VE_WANT;
|
||||||
@ -314,6 +327,58 @@ getenv_int(const char *var, int def)
|
|||||||
return (int)val;
|
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,
|
||||||
|
("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);
|
||||||
|
if (rc == VE_NOT_CHECKED) {
|
||||||
|
rc = find_manifest(filename);
|
||||||
|
} else {
|
||||||
|
ve_status_set(fd, rc);
|
||||||
|
}
|
||||||
|
return (rc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief verify an open file
|
* @brief verify an open file
|
||||||
*
|
*
|
||||||
@ -342,45 +407,26 @@ getenv_int(const char *var, int def)
|
|||||||
* @return >= 0 on success < 0 on failure
|
* @return >= 0 on success < 0 on failure
|
||||||
*/
|
*/
|
||||||
int
|
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 accept_no_fp = ACCEPT_NO_FP_DEFAULT;
|
||||||
static int verbose = VE_VERBOSE_DEFAULT;
|
static int verbose = VE_VERBOSE_DEFAULT;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *cp;
|
char *cp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (verifying < 0) {
|
rc = verify_prep(fd, filename, off, &st, caller);
|
||||||
verifying = ve_trust_init();
|
|
||||||
|
if (!rc)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if (!once) {
|
||||||
|
once++;
|
||||||
verbose = getenv_int("VE_VERBOSE", VE_VERBOSE_DEFAULT);
|
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);
|
|
||||||
|
|
||||||
if (fd < 0 || fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
rc = find_manifest(filename);
|
|
||||||
if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
|
if (rc != VE_FINGERPRINT_WRONG && loaded_manifests) {
|
||||||
if (severity <= VE_GUESS)
|
if (severity <= VE_GUESS)
|
||||||
severity = severity_guess(filename);
|
severity = severity_guess(filename);
|
||||||
@ -391,6 +437,12 @@ verify_file(int fd, const char *filename, off_t off, int severity)
|
|||||||
* order, which makes our pseudo pcr more useful.
|
* order, which makes our pseudo pcr more useful.
|
||||||
*/
|
*/
|
||||||
ve_pcr_updating_set((severity == VE_MUST));
|
ve_pcr_updating_set((severity == VE_MUST));
|
||||||
|
#endif
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
if (DestdirLen > 0 &&
|
||||||
|
strncmp(filename, Destdir, DestdirLen) == 0) {
|
||||||
|
filename += DestdirLen;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((rc = verify_fd(fd, filename, off, &st)) >= 0) {
|
if ((rc = verify_fd(fd, filename, off, &st)) >= 0) {
|
||||||
if (verbose || severity > VE_WANT) {
|
if (verbose || severity > VE_WANT) {
|
||||||
@ -412,8 +464,7 @@ verify_file(int fd, const char *filename, off_t off, int severity)
|
|||||||
if (strncmp(cp, "loader.ve.", 10) == 0) {
|
if (strncmp(cp, "loader.ve.", 10) == 0) {
|
||||||
cp += 10;
|
cp += 10;
|
||||||
verify_tweak(fd, off, &st, cp,
|
verify_tweak(fd, off, &st, cp,
|
||||||
&accept_no_fp, &verbose,
|
&accept_no_fp, &verbose);
|
||||||
&verifying);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,7 @@ __DEFAULT_DEPENDENT_OPTIONS= \
|
|||||||
CLANG_FULL/CLANG \
|
CLANG_FULL/CLANG \
|
||||||
LOADER_VERIEXEC/BEARSSL \
|
LOADER_VERIEXEC/BEARSSL \
|
||||||
LOADER_EFI_SECUREBOOT/LOADER_VERIEXEC \
|
LOADER_EFI_SECUREBOOT/LOADER_VERIEXEC \
|
||||||
|
LOADER_VERIEXEC_VECTX/LOADER_VERIEXEC \
|
||||||
VERIEXEC/BEARSSL \
|
VERIEXEC/BEARSSL \
|
||||||
|
|
||||||
# MK_*_SUPPORT options which default to "yes" unless their corresponding
|
# MK_*_SUPPORT options which default to "yes" unless their corresponding
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/linker_set.h>
|
#include <sys/linker_set.h>
|
||||||
|
|
||||||
|
#include "readin.h"
|
||||||
|
|
||||||
/* Commands and return values; nonzero return sets command_errmsg != NULL */
|
/* Commands and return values; nonzero return sets command_errmsg != NULL */
|
||||||
typedef int (bootblk_cmd_t)(int argc, char *argv[]);
|
typedef int (bootblk_cmd_t)(int argc, char *argv[]);
|
||||||
#define COMMAND_ERRBUFSZ (256)
|
#define COMMAND_ERRBUFSZ (256)
|
||||||
@ -70,8 +72,8 @@ void hexdump(caddr_t region, size_t len);
|
|||||||
size_t strlenout(vm_offset_t str);
|
size_t strlenout(vm_offset_t str);
|
||||||
char *strdupout(vm_offset_t str);
|
char *strdupout(vm_offset_t str);
|
||||||
void kern_bzero(vm_offset_t dest, size_t len);
|
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);
|
int kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off);
|
||||||
void *alloc_pread(int fd, off_t off, size_t len);
|
void *alloc_pread(readin_handle_t fd, off_t off, size_t len);
|
||||||
|
|
||||||
/* bcache.c */
|
/* bcache.c */
|
||||||
void bcache_init(size_t nblks, size_t bsize);
|
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,
|
ssize_t (*arch_copyout)(const vm_offset_t src, void *dest,
|
||||||
const size_t len);
|
const size_t len);
|
||||||
/* Read from file to module address space, same semantics as read() */
|
/* 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);
|
const size_t len);
|
||||||
/* Perform ISA byte port I/O (only for systems with ISA) */
|
/* Perform ISA byte port I/O (only for systems with ISA) */
|
||||||
int (*arch_isainb)(int port);
|
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")
|
#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LOADER_VERIEXEC
|
|
||||||
#include <verify_file.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !_BOOTSTRAP_H_ */
|
#endif /* !_BOOTSTRAP_H_ */
|
||||||
|
@ -284,7 +284,7 @@ bf_init(void)
|
|||||||
/* try to load and run init file if present */
|
/* try to load and run init file if present */
|
||||||
if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) {
|
if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) {
|
||||||
#ifdef LOADER_VERIEXEC
|
#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);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -386,7 +386,7 @@ interp_include(const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOADER_VERIEXEC
|
#ifdef LOADER_VERIEXEC
|
||||||
if (verify_file(fd, filename, 0, VE_GUESS) < 0) {
|
if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
sprintf(command_errbuf,"can't verify '%s'", filename);
|
sprintf(command_errbuf,"can't verify '%s'", filename);
|
||||||
return(CMD_ERROR);
|
return(CMD_ERROR);
|
||||||
|
@ -97,7 +97,7 @@ interp_include(const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOADER_VERIEXEC
|
#ifdef LOADER_VERIEXEC
|
||||||
if (verify_file(fd, filename, 0, VE_GUESS) < 0) {
|
if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
sprintf(command_errbuf,"can't verify '%s'", filename);
|
sprintf(command_errbuf,"can't verify '%s'", filename);
|
||||||
return(CMD_ERROR);
|
return(CMD_ERROR);
|
||||||
|
@ -71,8 +71,17 @@ typedef struct elf_file {
|
|||||||
size_t firstlen;
|
size_t firstlen;
|
||||||
int kernel;
|
int kernel;
|
||||||
uint64_t off;
|
uint64_t off;
|
||||||
|
#ifdef LOADER_VERIEXEC_VECTX
|
||||||
|
struct vectx *vctx;
|
||||||
|
#endif
|
||||||
} *elf_file_t;
|
} *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,
|
static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef,
|
||||||
uint64_t loadaddr);
|
uint64_t loadaddr);
|
||||||
static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef,
|
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);
|
close(ef->fd);
|
||||||
return (ENOMEM);
|
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;
|
ef->firstlen = (size_t)bytes_read;
|
||||||
if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) {
|
if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) {
|
||||||
err = EFTYPE; /* could be EIO, but may be small file */
|
err = EFTYPE; /* could be EIO, but may be small file */
|
||||||
@ -245,8 +267,8 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOADER_VERIEXEC
|
#if defined(LOADER_VERIEXEC) && !defined(LOADER_VERIEXEC_VECTX)
|
||||||
if (verify_file(ef->fd, filename, bytes_read, VE_MUST) < 0) {
|
if (verify_file(ef->fd, filename, bytes_read, VE_MUST, __func__) < 0) {
|
||||||
err = EAUTH;
|
err = EAUTH;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -259,6 +281,9 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef)
|
|||||||
ef->firstpage = NULL;
|
ef->firstpage = NULL;
|
||||||
}
|
}
|
||||||
if (ef->fd != -1) {
|
if (ef->fd != -1) {
|
||||||
|
#ifdef LOADER_VERIEXEC_VECTX
|
||||||
|
free(ef->vctx);
|
||||||
|
#endif
|
||||||
close(ef->fd);
|
close(ef->fd);
|
||||||
ef->fd = -1;
|
ef->fd = -1;
|
||||||
}
|
}
|
||||||
@ -415,8 +440,20 @@ __elfN(loadfile_raw)(char *filename, uint64_t dest,
|
|||||||
out:
|
out:
|
||||||
if (ef.firstpage)
|
if (ef.firstpage)
|
||||||
free(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);
|
close(ef.fd);
|
||||||
|
}
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,7 +599,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off)
|
|||||||
phdr[i].p_vaddr + off, fpcopy);
|
phdr[i].p_vaddr + off, fpcopy);
|
||||||
}
|
}
|
||||||
if (phdr[i].p_filesz > 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_filesz - fpcopy,
|
||||||
phdr[i].p_offset + fpcopy) != 0) {
|
phdr[i].p_offset + fpcopy) != 0) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
@ -606,7 +644,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;
|
chunk = (size_t)ehdr->e_shnum * (size_t)ehdr->e_shentsize;
|
||||||
if (chunk == 0 || ehdr->e_shoff == 0)
|
if (chunk == 0 || ehdr->e_shoff == 0)
|
||||||
goto nosyms;
|
goto nosyms;
|
||||||
shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk);
|
shdr = alloc_pread(VECTX_HANDLE(ef), ehdr->e_shoff, chunk);
|
||||||
if (shdr == NULL) {
|
if (shdr == NULL) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
"_loadimage: failed to read section headers");
|
"_loadimage: failed to read section headers");
|
||||||
@ -625,8 +663,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off)
|
|||||||
*/
|
*/
|
||||||
chunk = shdr[ehdr->e_shstrndx].sh_size;
|
chunk = shdr[ehdr->e_shstrndx].sh_size;
|
||||||
if (chunk) {
|
if (chunk) {
|
||||||
shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset,
|
shstr = alloc_pread(VECTX_HANDLE(ef),
|
||||||
chunk);
|
shdr[ehdr->e_shstrndx].sh_offset, chunk);
|
||||||
if (shstr) {
|
if (shstr) {
|
||||||
for (i = 0; i < ehdr->e_shnum; i++) {
|
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||||
if (strcmp(shstr + shdr[i].sh_name,
|
if (strcmp(shstr + shdr[i].sh_name,
|
||||||
@ -716,14 +754,14 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off)
|
|||||||
printf("0x%lx+0x%lx", (long)sizeof(size), (long)size);
|
printf("0x%lx+0x%lx", (long)sizeof(size), (long)size);
|
||||||
#endif
|
#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)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
"_loadimage: could not seek for symbols - skipped!");
|
"_loadimage: could not seek for symbols - skipped!");
|
||||||
lastaddr = ssym;
|
lastaddr = ssym;
|
||||||
ssym = 0;
|
ssym = 0;
|
||||||
goto nosyms;
|
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) {
|
if (result < 0 || (size_t)result != shdr[i].sh_size) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
"_loadimage: could not read symbols - skipped! "
|
"_loadimage: could not read symbols - skipped! "
|
||||||
@ -933,14 +971,14 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size = (size_t)ef.ehdr->e_shnum * (size_t)ef.ehdr->e_shentsize;
|
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) {
|
if (shdr == NULL) {
|
||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load shstrtab. */
|
/* 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);
|
shdr[ef.ehdr->e_shstrndx].sh_size);
|
||||||
if (shstrtab == NULL) {
|
if (shstrtab == NULL) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
@ -969,7 +1007,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Load set_modmetadata_set into memory */
|
/* 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) {
|
if (err != 0) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
"load_modmetadata: unable to load set_modmetadata_set: %d\n", err);
|
"load_modmetadata: unable to load set_modmetadata_set: %d\n", err);
|
||||||
@ -980,7 +1018,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
|
|||||||
dest += sh_meta->sh_size;
|
dest += sh_meta->sh_size;
|
||||||
|
|
||||||
/* Load data sections into memory. */
|
/* 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);
|
sh_data[0]->sh_offset);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
@ -995,7 +1033,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
|
|||||||
ef.off = -(sh_data[0]->sh_addr - dest);
|
ef.off = -(sh_data[0]->sh_addr - dest);
|
||||||
dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr);
|
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);
|
sh_data[1]->sh_offset);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
@ -1017,8 +1055,20 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
|
|||||||
free(shdr);
|
free(shdr);
|
||||||
if (ef.firstpage != NULL)
|
if (ef.firstpage != NULL)
|
||||||
free(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);
|
close(ef.fd);
|
||||||
|
}
|
||||||
return (err);
|
return (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +60,17 @@ typedef struct elf_file {
|
|||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
vm_offset_t off;
|
vm_offset_t off;
|
||||||
|
#ifdef LOADER_VERIEXEC_VECTX
|
||||||
|
struct vectx *vctx;
|
||||||
|
#endif
|
||||||
} *elf_file_t;
|
} *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,
|
static int __elfN(obj_loadimage)(struct preloaded_file *mp, elf_file_t ef,
|
||||||
uint64_t loadaddr);
|
uint64_t loadaddr);
|
||||||
static int __elfN(obj_lookup_set)(struct preloaded_file *mp, elf_file_t ef,
|
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);
|
return(EFTYPE);
|
||||||
if ((ef.fd = open(filename, O_RDONLY)) == -1)
|
if ((ef.fd = open(filename, O_RDONLY)) == -1)
|
||||||
return(errno);
|
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;
|
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)) {
|
if (bytes_read != sizeof(*hdr)) {
|
||||||
err = EFTYPE; /* could be EIO, but may be small file */
|
err = EFTYPE; /* could be EIO, but may be small file */
|
||||||
goto oerr;
|
goto oerr;
|
||||||
@ -129,8 +151,8 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest,
|
|||||||
goto oerr;
|
goto oerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOADER_VERIEXEC
|
#if defined(LOADER_VERIEXEC) && !defined(LOADER_VERIEXEC_VECTX)
|
||||||
if (verify_file(ef.fd, filename, bytes_read, VE_MUST) < 0) {
|
if (verify_file(ef.fd, filename, bytes_read, VE_MUST, __func__) < 0) {
|
||||||
err = EAUTH;
|
err = EAUTH;
|
||||||
goto oerr;
|
goto oerr;
|
||||||
}
|
}
|
||||||
@ -181,6 +203,17 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest,
|
|||||||
oerr:
|
oerr:
|
||||||
file_discard(fp);
|
file_discard(fp);
|
||||||
out:
|
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);
|
close(ef.fd);
|
||||||
if (ef.e_shdr != NULL)
|
if (ef.e_shdr != NULL)
|
||||||
free(ef.e_shdr);
|
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. */
|
/* Read in the section headers. */
|
||||||
shdrbytes = hdr->e_shnum * hdr->e_shentsize;
|
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) {
|
if (shdr == NULL) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
"_obj_loadimage: read section headers failed\n");
|
"_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)
|
if (cshdr == lshdr)
|
||||||
break;
|
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) {
|
cshdr->sh_size, (off_t)cshdr->sh_offset) != 0) {
|
||||||
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
|
||||||
"_obj_loadimage: read failed\n");
|
"_obj_loadimage: read failed\n");
|
||||||
|
@ -116,10 +116,10 @@ kern_bzero(vm_offset_t dest, size_t len)
|
|||||||
* and it just returns 0 if successful.
|
* and it just returns 0 if successful.
|
||||||
*/
|
*/
|
||||||
int
|
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
|
#ifdef DEBUG
|
||||||
printf("\nlseek failed\n");
|
printf("\nlseek failed\n");
|
||||||
#endif
|
#endif
|
||||||
@ -140,7 +140,7 @@ kern_pread(int fd, vm_offset_t dest, size_t len, off_t off)
|
|||||||
*/
|
*/
|
||||||
/* coverity[ -tainted_data_return ] */
|
/* coverity[ -tainted_data_return ] */
|
||||||
void *
|
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;
|
void *buf;
|
||||||
|
|
||||||
@ -152,14 +152,14 @@ alloc_pread(int fd, off_t off, size_t len)
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (lseek(fd, off, SEEK_SET) == -1) {
|
if (VECTX_LSEEK(fd, off, SEEK_SET) == -1) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("\nlseek failed\n");
|
printf("\nlseek failed\n");
|
||||||
#endif
|
#endif
|
||||||
free(buf);
|
free(buf);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if ((size_t)read(fd, buf, len) != len) {
|
if ((size_t)VECTX_READ(fd, buf, len) != len) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("\nread failed\n");
|
printf("\nread failed\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -616,6 +616,14 @@ file_load_dependencies(struct preloaded_file *base_file)
|
|||||||
return (error);
|
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,
|
* We've been asked to load (fname) as (type), so just suck it in,
|
||||||
* no arguments or anything.
|
* no arguments or anything.
|
||||||
@ -627,6 +635,10 @@ file_loadraw(const char *fname, char *type, int insert)
|
|||||||
char *name;
|
char *name;
|
||||||
int fd, got;
|
int fd, got;
|
||||||
vm_offset_t laddr;
|
vm_offset_t laddr;
|
||||||
|
#ifdef LOADER_VERIEXEC_VECTX
|
||||||
|
struct vectx *vctx;
|
||||||
|
int verror;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We can't load first */
|
/* We can't load first */
|
||||||
if ((file_findfile(NULL, NULL)) == NULL) {
|
if ((file_findfile(NULL, NULL)) == NULL) {
|
||||||
@ -649,13 +661,26 @@ file_loadraw(const char *fname, char *type, int insert)
|
|||||||
return(NULL);
|
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
|
#ifdef LOADER_VERIEXEC
|
||||||
if (verify_file(fd, name, 0, VE_MUST) < 0) {
|
if (verify_file(fd, name, 0, VE_MUST, __func__) < 0) {
|
||||||
sprintf(command_errbuf, "can't verify '%s'", name);
|
sprintf(command_errbuf, "can't verify '%s': %s",
|
||||||
|
name, ve_error_get());
|
||||||
free(name);
|
free(name);
|
||||||
close(fd);
|
close(fd);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (archsw.arch_loadaddr != NULL)
|
if (archsw.arch_loadaddr != NULL)
|
||||||
@ -666,7 +691,7 @@ file_loadraw(const char *fname, char *type, int insert)
|
|||||||
laddr = loadaddr;
|
laddr = loadaddr;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* read in 4k chunks; size is not really important */
|
/* 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 */
|
if (got == 0) /* end of file */
|
||||||
break;
|
break;
|
||||||
if (got < 0) { /* error */
|
if (got < 0) { /* error */
|
||||||
@ -674,12 +699,24 @@ file_loadraw(const char *fname, char *type, int insert)
|
|||||||
"error reading '%s': %s", name, strerror(errno));
|
"error reading '%s': %s", name, strerror(errno));
|
||||||
free(name);
|
free(name);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
#ifdef LOADER_VERIEXEC_VECTX
|
||||||
|
free(vctx);
|
||||||
|
#endif
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
laddr += got;
|
laddr += got;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr));
|
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 */
|
/* Looks OK so far; create & populate control structure */
|
||||||
fp = file_alloc();
|
fp = file_alloc();
|
||||||
|
@ -51,9 +51,8 @@ i386_copyout(const vm_offset_t src, void *dest, const size_t len)
|
|||||||
return(len);
|
return(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
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));
|
||||||
}
|
}
|
||||||
|
@ -341,14 +341,14 @@ efi_copyout(const vm_offset_t src, void *dest, const size_t len)
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
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 (!efi_check_space(dest + stage_offset + len)) {
|
if (!efi_check_space(dest + stage_offset + len)) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
return (read(fd, (void *)(dest + stage_offset), len));
|
return (VECTX_READ(fd, (void *)(dest + stage_offset), len));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define _LOADER_EFI_COPY_H_
|
#define _LOADER_EFI_COPY_H_
|
||||||
|
|
||||||
#include <stand.h>
|
#include <stand.h>
|
||||||
|
#include <readin.h>
|
||||||
|
|
||||||
int efi_autoload(void);
|
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_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_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_translate(vm_offset_t ptr);
|
||||||
|
|
||||||
void efi_copy_finish(void);
|
void efi_copy_finish(void);
|
||||||
|
@ -1460,7 +1460,7 @@ command_chain(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOADER_VERIEXEC
|
#ifdef LOADER_VERIEXEC
|
||||||
if (verify_file(fd, name, 0, VE_MUST) < 0) {
|
if (verify_file(fd, name, 0, VE_MUST, __func__) < 0) {
|
||||||
sprintf(command_errbuf, "can't verify: %s", name);
|
sprintf(command_errbuf, "can't verify: %s", name);
|
||||||
close(fd);
|
close(fd);
|
||||||
return (CMD_ERROR);
|
return (CMD_ERROR);
|
||||||
|
@ -530,7 +530,7 @@ static void pfopen(FICL_VM *pVM)
|
|||||||
fd = open(name, mode);
|
fd = open(name, mode);
|
||||||
#ifdef LOADER_VERIEXEC
|
#ifdef LOADER_VERIEXEC
|
||||||
if (fd >= 0) {
|
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 */
|
/* not verified writing ok but reading is not */
|
||||||
if ((mode & O_ACCMODE) != O_WRONLY) {
|
if ((mode & O_ACCMODE) != O_WRONLY) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -63,7 +63,7 @@ i386_copyout(const vm_offset_t src, void *dest, const size_t len)
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
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) {
|
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 (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (read(fd, PTOV(dest), len));
|
return (VECTX_READ(fd, PTOV(dest), len));
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,8 @@ extern struct devdesc currdev; /* our current device */
|
|||||||
#define MAXDEV 31 /* maximum number of distinct devices */
|
#define MAXDEV 31 /* maximum number of distinct devices */
|
||||||
#define MAXBDDEV MAXDEV
|
#define MAXBDDEV MAXDEV
|
||||||
|
|
||||||
|
#include <readin.h>
|
||||||
|
|
||||||
/* exported devices XXX rename? */
|
/* exported devices XXX rename? */
|
||||||
extern struct devsw bioscd;
|
extern struct devsw bioscd;
|
||||||
extern struct devsw biosfd;
|
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_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_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;
|
struct preloaded_file;
|
||||||
void bios_addsmapdata(struct preloaded_file *);
|
void bios_addsmapdata(struct preloaded_file *);
|
||||||
|
@ -43,6 +43,12 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include "libi386/libi386.h"
|
#include "libi386/libi386.h"
|
||||||
#include "btxv86.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.
|
* The MBR/VBR is located in first sector of disk/partition.
|
||||||
* Read 512B to temporary location and set up relocation. Then
|
* Read 512B to temporary location and set up relocation. Then
|
||||||
@ -59,6 +65,10 @@ command_chain(int argc, char *argv[])
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
vm_offset_t mem = 0x100000;
|
vm_offset_t mem = 0x100000;
|
||||||
struct i386_devdesc *rootdev;
|
struct i386_devdesc *rootdev;
|
||||||
|
#ifdef LOADER_VERIEXEC_VECTX
|
||||||
|
struct vectx *vctx;
|
||||||
|
int verror;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
command_errmsg = "no device or file name specified";
|
command_errmsg = "no device or file name specified";
|
||||||
@ -75,6 +85,15 @@ command_chain(int argc, char *argv[])
|
|||||||
return (CMD_ERROR);
|
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
|
#ifdef LOADER_VERIEXEC
|
||||||
if (verify_file(fd, argv[1], 0, VE_MUST) < 0) {
|
if (verify_file(fd, argv[1], 0, VE_MUST) < 0) {
|
||||||
sprintf(command_errbuf, "can't verify: %s", argv[1]);
|
sprintf(command_errbuf, "can't verify: %s", argv[1]);
|
||||||
@ -82,7 +101,7 @@ command_chain(int argc, char *argv[])
|
|||||||
return (CMD_ERROR);
|
return (CMD_ERROR);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
len = strlen(argv[1]);
|
len = strlen(argv[1]);
|
||||||
if (argv[1][len-1] != ':') {
|
if (argv[1][len-1] != ':') {
|
||||||
if (fstat(fd, &st) == -1) {
|
if (fstat(fd, &st) == -1) {
|
||||||
@ -104,13 +123,19 @@ command_chain(int argc, char *argv[])
|
|||||||
return (CMD_ERROR);
|
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";
|
command_errmsg = "failed to read disk";
|
||||||
close(fd);
|
close(fd);
|
||||||
return (CMD_ERROR);
|
return (CMD_ERROR);
|
||||||
}
|
}
|
||||||
close(fd);
|
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] == ':' &&
|
if (argv[1][len-1] == ':' &&
|
||||||
*((uint16_t *)PTOV(mem + DOSMAGICOFFSET)) != DOSMAGIC) {
|
*((uint16_t *)PTOV(mem + DOSMAGICOFFSET)) != DOSMAGIC) {
|
||||||
command_errmsg = "wrong magic";
|
command_errmsg = "wrong magic";
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "openfirm.h"
|
#include "openfirm.h"
|
||||||
|
#include <readin.h>
|
||||||
|
|
||||||
struct ofw_devdesc {
|
struct ofw_devdesc {
|
||||||
struct devdesc dd;
|
struct devdesc dd;
|
||||||
@ -51,7 +52,7 @@ int ofwn_getunit(const char *);
|
|||||||
|
|
||||||
ssize_t ofw_copyin(const void *src, vm_offset_t dest, const size_t len);
|
ssize_t ofw_copyin(const void *src, vm_offset_t dest, const size_t len);
|
||||||
ssize_t ofw_copyout(const vm_offset_t src, void *dest, const size_t len);
|
ssize_t ofw_copyout(const vm_offset_t src, void *dest, const size_t len);
|
||||||
ssize_t ofw_readin(const int fd, vm_offset_t dest, const size_t len);
|
ssize_t ofw_readin(readin_handle_t fd, vm_offset_t dest, const size_t len);
|
||||||
|
|
||||||
extern int ofw_boot(void);
|
extern int ofw_boot(void);
|
||||||
extern int ofw_autoload(void);
|
extern int ofw_autoload(void);
|
||||||
|
@ -133,7 +133,7 @@ ofw_copyout(const vm_offset_t src, void *dest, const size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
ofw_readin(const int fd, vm_offset_t dest, const size_t len)
|
ofw_readin(readin_handle_t fd, vm_offset_t dest, const size_t len)
|
||||||
{
|
{
|
||||||
void *buf;
|
void *buf;
|
||||||
size_t resid, chunk, get;
|
size_t resid, chunk, get;
|
||||||
@ -157,7 +157,7 @@ ofw_readin(const int fd, vm_offset_t dest, const size_t len)
|
|||||||
|
|
||||||
for (resid = len; resid > 0; resid -= got, p += got) {
|
for (resid = len; resid > 0; resid -= got, p += got) {
|
||||||
get = min(chunk, resid);
|
get = min(chunk, resid);
|
||||||
got = read(fd, buf, get);
|
got = VECTX_READ(fd, buf, get);
|
||||||
|
|
||||||
if (got <= 0) {
|
if (got <= 0) {
|
||||||
if (got < 0)
|
if (got < 0)
|
||||||
|
@ -73,6 +73,9 @@ SRCS+= interp_simple.c
|
|||||||
|
|
||||||
.if ${MK_LOADER_VERIEXEC} != "no"
|
.if ${MK_LOADER_VERIEXEC} != "no"
|
||||||
CFLAGS+= -DLOADER_VERIEXEC -I${SRCTOP}/lib/libsecureboot/h
|
CFLAGS+= -DLOADER_VERIEXEC -I${SRCTOP}/lib/libsecureboot/h
|
||||||
|
.if ${MK_LOADER_VERIEXEC_VECTX} != "no"
|
||||||
|
CFLAGS+= -DLOADER_VERIEXEC_VECTX
|
||||||
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${MK_LOADER_VERIEXEC_PASS_MANIFEST} != "no"
|
.if ${MK_LOADER_VERIEXEC_PASS_MANIFEST} != "no"
|
||||||
|
@ -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_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 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 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 = {
|
struct arch_switch archsw = {
|
||||||
.arch_autoload = beri_arch_autoload,
|
.arch_autoload = beri_arch_autoload,
|
||||||
@ -90,8 +90,8 @@ beri_arch_loadaddr(u_int type, void *data, uint64_t addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
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));
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <fdt_platform.h>
|
#include <fdt_platform.h>
|
||||||
|
|
||||||
#include <machine/cpufunc.h>
|
#include <machine/cpufunc.h>
|
||||||
#include "bootstrap.h"
|
#include <bootstrap.h>
|
||||||
#include "host_syscall.h"
|
#include "host_syscall.h"
|
||||||
|
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ extern void *_end;
|
|||||||
int kboot_getdev(void **vdev, const char *devspec, const char **path);
|
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_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_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);
|
int kboot_autoload(void);
|
||||||
uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr);
|
uint64_t kboot_loadaddr(u_int type, void *data, uint64_t addr);
|
||||||
int kboot_setcurrdev(struct env_var *ev, int flags, const void *value);
|
int kboot_setcurrdev(struct env_var *ev, int flags, const void *value);
|
||||||
@ -410,7 +410,7 @@ kboot_copyout(vm_offset_t src, void *dest, const size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
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;
|
void *buf;
|
||||||
size_t resid, chunk, get;
|
size_t resid, chunk, get;
|
||||||
@ -428,7 +428,7 @@ kboot_readin(const int fd, vm_offset_t dest, const size_t len)
|
|||||||
|
|
||||||
for (resid = len; resid > 0; resid -= got, p += got) {
|
for (resid = len; resid > 0; resid -= got, p += got) {
|
||||||
get = min(chunk, resid);
|
get = min(chunk, resid);
|
||||||
got = read(fd, buf, get);
|
got = VECTX_READ(fd, buf, get);
|
||||||
if (got <= 0) {
|
if (got <= 0) {
|
||||||
if (got < 0)
|
if (got < 0)
|
||||||
printf("kboot_readin: read failed\n");
|
printf("kboot_readin: read failed\n");
|
||||||
|
@ -160,7 +160,7 @@ uboot_copyout(const vm_offset_t src, void *dest, const size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
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));
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <disk.h>
|
#include <disk.h>
|
||||||
|
#include <readin.h>
|
||||||
|
|
||||||
struct uboot_devdesc {
|
struct uboot_devdesc {
|
||||||
union {
|
union {
|
||||||
@ -62,7 +63,7 @@ extern uintptr_t uboot_heap_end;
|
|||||||
uint64_t uboot_loadaddr(u_int type, void *data, uint64_t addr);
|
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_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_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);
|
extern int uboot_autoload(void);
|
||||||
|
|
||||||
struct preloaded_file;
|
struct preloaded_file;
|
||||||
|
@ -48,7 +48,7 @@ userboot_copyout(vm_offset_t va, void *dst, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
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;
|
ssize_t res, s;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
@ -59,7 +59,7 @@ userboot_readin(int fd, vm_offset_t va, size_t len)
|
|||||||
sz = len;
|
sz = len;
|
||||||
if (sz > sizeof(buf))
|
if (sz > sizeof(buf))
|
||||||
sz = sizeof(buf);
|
sz = sizeof(buf);
|
||||||
s = read(fd, buf, sz);
|
s = VECTX_READ(fd, buf, sz);
|
||||||
if (s == 0)
|
if (s == 0)
|
||||||
break;
|
break;
|
||||||
if (s < 0)
|
if (s < 0)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "userboot.h"
|
#include "userboot.h"
|
||||||
|
#include <readin.h>
|
||||||
|
|
||||||
extern struct loader_callbacks *callbacks;
|
extern struct loader_callbacks *callbacks;
|
||||||
extern void *callbacks_arg;
|
extern void *callbacks_arg;
|
||||||
@ -54,7 +55,7 @@ extern void delay(int);
|
|||||||
extern int userboot_autoload(void);
|
extern int userboot_autoload(void);
|
||||||
extern ssize_t userboot_copyin(const void *, vm_offset_t, size_t);
|
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_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 **);
|
extern int userboot_getdev(void **, const char *, const char **);
|
||||||
char *userboot_fmtdev(void *vdev);
|
char *userboot_fmtdev(void *vdev);
|
||||||
int userboot_setcurrdev(struct env_var *ev, int flags, const void *value);
|
int userboot_setcurrdev(struct env_var *ev, int flags, const void *value);
|
||||||
|
Loading…
Reference in New Issue
Block a user