Files
Frediano Ziglio 32204e8e19 libs/guest: Reduce number of iovecs in write_split_record()
Construct xc_sr_rhdr directly rather than in two halves.

Use size_t for combined_len, which allows the later size check to spot a few
more cases which might have truncated.

Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Anthony PERARD <anthony.perard@vates.tech>
2026-07-08 15:35:45 +01:00

168 lines
4.9 KiB
C

#include <assert.h>
#include "xg_sr_common.h"
#include <xen-tools/common-macros.h>
static const char *const dhdr_types[] =
{
[DHDR_TYPE_X86_PV] = "x86 PV",
[DHDR_TYPE_X86_HVM] = "x86 HVM",
};
const char *dhdr_type_to_str(uint32_t type)
{
if ( type < ARRAY_SIZE(dhdr_types) && dhdr_types[type] )
return dhdr_types[type];
return "Reserved";
}
static const char *const mandatory_rec_types[] =
{
[REC_TYPE_END] = "End",
[REC_TYPE_PAGE_DATA] = "Page data",
[REC_TYPE_X86_PV_INFO] = "x86 PV info",
[REC_TYPE_X86_PV_P2M_FRAMES] = "x86 PV P2M frames",
[REC_TYPE_X86_PV_VCPU_BASIC] = "x86 PV vcpu basic",
[REC_TYPE_X86_PV_VCPU_EXTENDED] = "x86 PV vcpu extended",
[REC_TYPE_X86_PV_VCPU_XSAVE] = "x86 PV vcpu xsave",
[REC_TYPE_SHARED_INFO] = "Shared info",
[REC_TYPE_X86_TSC_INFO] = "x86 TSC info",
[REC_TYPE_HVM_CONTEXT] = "HVM context",
[REC_TYPE_HVM_PARAMS] = "HVM params",
[REC_TYPE_TOOLSTACK] = "Toolstack",
[REC_TYPE_X86_PV_VCPU_MSRS] = "x86 PV vcpu msrs",
[REC_TYPE_VERIFY] = "Verify",
[REC_TYPE_CHECKPOINT] = "Checkpoint",
[REC_TYPE_CHECKPOINT_DIRTY_PFN_LIST] = "Checkpoint dirty pfn list",
[REC_TYPE_STATIC_DATA_END] = "Static data end",
[REC_TYPE_X86_CPUID_POLICY] = "x86 CPUID policy",
[REC_TYPE_X86_MSR_POLICY] = "x86 MSR policy",
};
const char *rec_type_to_str(uint32_t type)
{
if ( !(type & REC_TYPE_OPTIONAL) )
{
if ( (type < ARRAY_SIZE(mandatory_rec_types)) &&
(mandatory_rec_types[type]) )
return mandatory_rec_types[type];
}
return "Reserved";
}
int write_split_record(struct xc_sr_context *ctx, struct xc_sr_record *rec,
void *buf, size_t sz)
{
static const char zeroes[REC_ALIGN] = {};
xc_interface *xch = ctx->xch;
size_t combined_length = rec->length + sz;
size_t record_length = ROUNDUP(combined_length, REC_ALIGN);
struct xc_sr_rhdr rhdr = { rec->type, combined_length };
struct iovec parts[] = {
{ &rhdr, sizeof(rhdr) },
{ rec->data, rec->length },
{ buf, sz },
{ (void *)zeroes, record_length - combined_length },
};
if ( record_length > REC_LENGTH_MAX )
{
ERROR("Record (0x%08x, %s) length %#zx exceeds max (%#x)", rec->type,
rec_type_to_str(rec->type), record_length, REC_LENGTH_MAX);
return -1;
}
if ( rec->length )
assert(rec->data);
if ( sz )
assert(buf);
if ( writev_exact(ctx->fd, parts, ARRAY_SIZE(parts)) )
goto err;
return 0;
err:
PERROR("Unable to write record to stream");
return -1;
}
int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec)
{
xc_interface *xch = ctx->xch;
struct xc_sr_rhdr rhdr;
size_t datasz;
if ( read_exact(fd, &rhdr, sizeof(rhdr)) )
{
PERROR("Failed to read Record Header from stream");
return -1;
}
if ( rhdr.length > REC_LENGTH_MAX )
{
ERROR("Record (0x%08x, %s) length %#x exceeds max (%#x)", rhdr.type,
rec_type_to_str(rhdr.type), rhdr.length, REC_LENGTH_MAX);
return -1;
}
datasz = ROUNDUP(rhdr.length, REC_ALIGN);
if ( datasz )
{
rec->data = malloc(datasz);
if ( !rec->data )
{
ERROR("Unable to allocate %zu bytes for record data (0x%08x, %s)",
datasz, rhdr.type, rec_type_to_str(rhdr.type));
return -1;
}
if ( read_exact(fd, rec->data, datasz) )
{
free(rec->data);
rec->data = NULL;
PERROR("Failed to read %zu bytes of data for record (0x%08x, %s)",
datasz, rhdr.type, rec_type_to_str(rhdr.type));
return -1;
}
}
else
rec->data = NULL;
rec->type = rhdr.type;
rec->length = rhdr.length;
return 0;
};
static void __attribute__((unused)) build_assertions(void)
{
BUILD_BUG_ON(sizeof(struct xc_sr_ihdr) != 24);
BUILD_BUG_ON(sizeof(struct xc_sr_dhdr) != 16);
BUILD_BUG_ON(sizeof(struct xc_sr_rhdr) != 8);
BUILD_BUG_ON(sizeof(struct xc_sr_rec_page_data_header) != 8);
BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_pv_info) != 8);
BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_pv_p2m_frames) != 8);
BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_pv_vcpu_hdr) != 8);
BUILD_BUG_ON(sizeof(struct xc_sr_rec_x86_tsc_info) != 24);
BUILD_BUG_ON(sizeof(struct xc_sr_rec_hvm_params_entry) != 16);
BUILD_BUG_ON(sizeof(struct xc_sr_rec_hvm_params) != 8);
}
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/