Pass severity to vectx_open() rather than vectx_close()

file_loadraw() can have a need to load unverified files
like "dtrace_dof".  Allow severity_guess() to look at the filename
but if it returns less than VE_MUST check that the type is not
one we insist on verifying.

In vectx_open if severity < VE_MUST we can allow it to be unverified.
If passed VE_GUESS we call severity_guess().
Regardless, we record severity in ctx so it is available to vectx_close().

Sponsored by: Hewlett Packard Enterprise Development LP

Reviewed by:	khng
Differential Revision:	https://reviews.freebsd.org/D56297
This commit is contained in:
Simon J. Gerraty
2026-04-10 10:43:15 -07:00
parent fc68534a9a
commit 35bbdfad28
9 changed files with 64 additions and 32 deletions
+3 -2
View File
@@ -51,6 +51,7 @@ 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 severity_guess(const char *);
void verify_report(const char *, int, int, struct stat *);
int verify_file(int, const char *, off_t, int, const char *);
void verify_pcr_export(void);
@@ -59,9 +60,9 @@ int is_verified(struct stat *);
void add_verify_status(struct stat *, int);
struct vectx;
struct vectx* vectx_open(int, const char *, off_t, struct stat *, int *, const char *);
struct vectx* vectx_open(int, const char *, int, 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 *);
int vectx_close(struct vectx *, const char *);
#endif /* _VERIFY_FILE_H_ */
+3 -3
View File
@@ -170,8 +170,8 @@ main(int argc, char *argv[])
fstat(fd, &st);
lseek(fd, 0, SEEK_SET);
off = st.st_size % 512;
vp = vectx_open(fd, argv[optind], off,
&st, &error, __func__);
vp = vectx_open(fd, argv[optind], VE_GUESS,
off, &st, &error, __func__);
if (!vp) {
printf("vectx_open(%s) failed: %d %s\n",
argv[optind], error,
@@ -190,7 +190,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, VE_MUST, __func__);
error = vectx_close(vp, __func__);
if (error) {
printf("vectx_close(%s) == %d %s\n",
argv[optind], error,
+32 -16
View File
@@ -60,6 +60,7 @@ struct vectx {
int vec_fd; /* file descriptor */
int vec_status; /* verification status */
int vec_closing; /* we are closing */
int vec_severity; /* usually VE_MUST */
};
@@ -93,7 +94,8 @@ 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,
vectx_open(int fd, const char *path, int severity,
off_t off, struct stat *stp,
int *error, const char *caller)
{
struct vectx *ctx;
@@ -106,14 +108,19 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
stp = &st;
rc = verify_prep(fd, path, off, stp, __func__);
if (severity == VE_GUESS)
severity = severity_guess(path);
DEBUG_PRINTF(2,
("vectx_open: caller=%s,fd=%d,name='%s',prep_rc=%d\n",
caller, fd, path, rc));
("vectx_open: caller=%s,fd=%d,name='%s',prep_rc=%d,severity=%d\n",
caller, fd, path, rc, severity));
switch (rc) {
case VE_FINGERPRINT_NONE:
case VE_FINGERPRINT_UNKNOWN:
if (severity < VE_MUST)
break;
/* FALLTHROUGH */
case VE_FINGERPRINT_WRONG:
*error = rc;
return (NULL);
@@ -127,19 +134,24 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
ctx->vec_off = 0;
ctx->vec_hashed = 0;
ctx->vec_want = NULL;
ctx->vec_severity = severity;
ctx->vec_status = 0;
ctx->vec_hashsz = hashsz = 0;
ctx->vec_closing = 0;
if (rc == 0) {
if (rc == VE_UNVERIFIED_OK) {
/* we are not verifying this */
*error = 0;
return (ctx);
}
cp = fingerprint_info_lookup(fd, path);
if (!cp) {
ctx->vec_status = VE_FINGERPRINT_NONE;
ve_error_set("%s: no entry", path);
if (severity < VE_MUST)
ctx->vec_status = VE_UNVERIFIED_OK;
else {
ctx->vec_status = VE_FINGERPRINT_NONE;
ve_error_set("%s: no entry", path);
}
} else {
if (strncmp(cp, "no_hash", 7) == 0) {
ctx->vec_status = VE_FINGERPRINT_IGNORE;
@@ -167,8 +179,12 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
cp += 7;
#endif
} else {
ctx->vec_status = VE_FINGERPRINT_UNKNOWN;
ve_error_set("%s: no supported fingerprint", path);
if (severity < VE_MUST)
ctx->vec_status = VE_UNVERIFIED_OK;
else {
ctx->vec_status = VE_FINGERPRINT_UNKNOWN;
ve_error_set("%s: no supported fingerprint", path);
}
}
}
*error = ctx->vec_status;
@@ -183,9 +199,9 @@ vectx_open(int fd, const char *path, off_t off, struct stat *stp,
}
}
DEBUG_PRINTF(2,
("vectx_open: caller=%s,name='%s',hashsz=%lu,status=%d\n",
("vectx_open: caller=%s,name='%s',hashsz=%lu,severity=%d,status=%d\n",
caller, path, (unsigned long)ctx->vec_hashsz,
ctx->vec_status));
severity, ctx->vec_status));
return (ctx);
enomem: /* unlikely */
@@ -379,7 +395,7 @@ vectx_lseek(struct vectx *ctx, off_t off, int whence)
* @return 0 or an error.
*/
int
vectx_close(struct vectx *ctx, int severity, const char *caller)
vectx_close(struct vectx *ctx, const char *caller)
{
int rc;
@@ -393,7 +409,7 @@ vectx_close(struct vectx *ctx, int severity, const char *caller)
* these tend to be processed in a more deterministic
* order, which makes our pseudo pcr more useful.
*/
ve_pcr_updating_set((severity == VE_MUST));
ve_pcr_updating_set((ctx->vec_severity == VE_MUST));
#endif
/* make sure we have hashed it all */
vectx_lseek(ctx, 0, SEEK_END);
@@ -401,13 +417,13 @@ vectx_close(struct vectx *ctx, int severity, const char *caller)
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));
verify_report(ctx->vec_path, severity, rc, NULL);
("vectx_close: caller=%s,name='%s',severity=%d,rc=%d\n",
caller,ctx->vec_path, ctx->vec_severity, rc));
verify_report(ctx->vec_path, ctx->vec_severity, rc, NULL);
if (rc == VE_FINGERPRINT_WRONG) {
#if !defined(UNIT_TEST) && !defined(DEBUG_VECTX)
/* we are generally called with VE_MUST */
if (severity > VE_WANT)
if (ctx->vec_severity > VE_WANT)
panic("cannot continue");
#endif
}
+2 -1
View File
@@ -271,7 +271,7 @@ find_manifest(const char *name)
# define ACCEPT_NO_FP_DEFAULT VE_MUST
#endif
static int
int
severity_guess(const char *filename)
{
const char *cp;
@@ -285,6 +285,7 @@ severity_guess(const char *filename)
*/
if ((cp = strrchr(filename, '.'))) {
if (strcmp(cp, ".cookie") == 0 ||
strcmp(cp, ".dof") == 0 ||
strcmp(cp, ".hints") == 0 ||
strcmp(cp, ".order") == 0 ||
strcmp(cp, ".tgz") == 0)
+1 -1
View File
@@ -308,7 +308,7 @@ command_set(int argc, char *argv[])
ves = ve_status_get(-1);
if (ves == VE_UNVERIFIED_OK) {
#ifdef LOADER_VERIEXEC_TESTING
printf("Checking: %s\n", var);
printf("Checking: %s\n", argv[1]);
#endif
if (is_restricted_var(argv[1])) {
printf("Ignoring restricted variable: %s\n",
+4 -3
View File
@@ -283,7 +283,8 @@ __elfN(load_elf_header)(char *filename, elf_file_t ef)
{
int verror;
ef->vctx = vectx_open(ef->fd, filename, 0L, NULL, &verror, __func__);
ef->vctx = vectx_open(ef->fd, filename, VE_MUST,
0L, NULL, &verror, __func__);
if (verror) {
printf("Unverified %s: %s\n", filename, ve_error_get());
close(ef->fd);
@@ -504,7 +505,7 @@ __elfN(loadfile_raw)(char *filename, uint64_t dest,
if (!err && ef.vctx) {
int verror;
verror = vectx_close(ef.vctx, VE_MUST, __func__);
verror = vectx_close(ef.vctx, __func__);
if (verror) {
err = EAUTH;
file_discard(fp);
@@ -1095,7 +1096,7 @@ __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest)
if (!err && ef.vctx) {
int verror;
verror = vectx_close(ef.vctx, VE_MUST, __func__);
verror = vectx_close(ef.vctx, __func__);
if (verror) {
err = EAUTH;
file_discard(fp);
+3 -2
View File
@@ -104,7 +104,8 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest,
{
int verror;
ef.vctx = vectx_open(ef.fd, filename, 0L, NULL, &verror, __func__);
ef.vctx = vectx_open(ef.fd, filename, VE_MUST,
0L, NULL, &verror, __func__);
if (verror) {
printf("Unverified %s: %s\n", filename, ve_error_get());
close(ef.fd);
@@ -196,7 +197,7 @@ __elfN(obj_loadfile)(char *filename, uint64_t dest,
if (!err && ef.vctx) {
int verror;
verror = vectx_close(ef.vctx, VE_MUST, __func__);
verror = vectx_close(ef.vctx, __func__);
if (verror) {
err = EAUTH;
file_discard(fp);
+14 -2
View File
@@ -661,6 +661,7 @@ file_loadraw(const char *fname, const char *type, int insert)
vm_offset_t laddr;
#ifdef LOADER_VERIEXEC_VECTX
struct vectx *vctx;
int severity;
int verror;
#endif
@@ -690,7 +691,16 @@ file_loadraw(const char *fname, const char *type, int insert)
}
#ifdef LOADER_VERIEXEC_VECTX
vctx = vectx_open(fd, name, 0L, NULL, &verror, __func__);
severity = severity_guess(name);
if (severity < VE_MUST) {
/* double check against type */
if (strcmp(type, "md_image") == 0
|| strcmp(type, "mfs_root") == 0
|| strcmp(type, "acpi_dsdt") == 0
|| strcmp(type, "cpu_microcode") == 0)
severity = VE_MUST;
}
vctx = vectx_open(fd, name, severity, 0L, NULL, &verror, __func__);
if (verror) {
sprintf(command_errbuf, "can't verify '%s': %s",
name, ve_error_get());
@@ -741,7 +751,9 @@ file_loadraw(const char *fname, const char *type, int insert)
if (module_verbose > MODULE_VERBOSE_SILENT)
printf("size=%#jx\n", (uintmax_t)(laddr - loadaddr));
#ifdef LOADER_VERIEXEC_VECTX
verror = vectx_close(vctx, VE_MUST, __func__);
verror = vectx_close(vctx, __func__);
DEBUG_PRINTF(1,("%s: vectx_close(%s): %d\n", __func__,
name, verror));
if (verror) {
free(name);
close(fd);
+2 -2
View File
@@ -83,7 +83,7 @@ command_chain(int argc, char *argv[])
}
#ifdef LOADER_VERIEXEC_VECTX
vctx = vectx_open(fd, argv[1], 0L, NULL, &verror, __func__);
vctx = vectx_open(fd, argv[1], VE_MUST, 0L, NULL, &verror, __func__);
if (verror) {
sprintf(command_errbuf, "can't verify: %s", argv[1]);
close(fd);
@@ -127,7 +127,7 @@ command_chain(int argc, char *argv[])
}
close(fd);
#ifdef LOADER_VERIEXEC_VECTX
verror = vectx_close(vctx, VE_MUST, __func__);
verror = vectx_close(vctx, __func__);
if (verror) {
free(vctx);
return (CMD_ERROR);