mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-17 16:47:50 +00:00
compel: fix heap alignment for structs with xsave state
struct parasite_ctl, parasite_thread_ctl, and plain_regs_struct all contain user_fpregs_struct_t (typedef for struct xsave_struct), which is declared with __aligned(64). When these structs are allocated on the heap with xmalloc/xzalloc (i.e. malloc/calloc), the allocator only guarantees 16-byte alignment on x86_64. The compiler, seeing the __aligned(64) attribute on the struct type, may emit aligned memory instructions (e.g. movaps, vmovdqa) for struct copies, assuming the memory is properly aligned. When the heap pointer is not 64-byte aligned, these instructions trigger a General Protection Fault (#GP). This was observed as a crash in save_regs_plain() at infect.c:1314 (prs->regs = *r) on CentOS Stream 10 under QEMU/KVM, where the compiler generated aligned vector instructions for the struct copy. The crash did not reproduce on bare metal with a different compiler version that happened to emit unaligned instructions. Add xmemalign() wrapper around posix_memalign() to xmalloc.h and use it for all three allocation sites: - compel_prepare_noctx(): struct parasite_ctl - compel_prepare_thread(): struct parasite_thread_ctl - compel_prepare(): struct plain_regs_struct Memory from posix_memalign() can be freed with free(), so no changes to cleanup paths are needed. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Adrian Reber <areber@redhat.com>
This commit is contained in:
parent
e39ff52283
commit
4bcf08ce7f
2 changed files with 15 additions and 3 deletions
|
|
@ -1115,7 +1115,7 @@ struct parasite_thread_ctl *compel_prepare_thread(struct parasite_ctl *ctl, int
|
|||
{
|
||||
struct parasite_thread_ctl *tctl;
|
||||
|
||||
tctl = xmalloc(sizeof(*tctl));
|
||||
tctl = xmemalign(__alignof__(*tctl), sizeof(*tctl));
|
||||
if (tctl) {
|
||||
if (prepare_thread(pid, &tctl->th)) {
|
||||
xfree(tctl);
|
||||
|
|
@ -1160,11 +1160,12 @@ struct parasite_ctl *compel_prepare_noctx(int pid)
|
|||
/*
|
||||
* Control block early setup.
|
||||
*/
|
||||
ctl = xzalloc(sizeof(*ctl));
|
||||
ctl = xmemalign(__alignof__(*ctl), sizeof(*ctl));
|
||||
if (!ctl) {
|
||||
pr_err("Parasite control block allocation failed (pid: %d)\n", pid);
|
||||
goto err;
|
||||
}
|
||||
memset(ctl, 0, sizeof(*ctl));
|
||||
|
||||
ctl->tsock = -1;
|
||||
ctl->ictx.log_fd = -1;
|
||||
|
|
@ -1363,7 +1364,8 @@ struct parasite_ctl *compel_prepare(int pid)
|
|||
|
||||
ictx->save_regs = save_regs_plain;
|
||||
ictx->make_sigframe = make_sigframe_plain;
|
||||
ictx->regs_arg = xmalloc(sizeof(struct plain_regs_struct));
|
||||
ictx->regs_arg = xmemalign(__alignof__(struct plain_regs_struct),
|
||||
sizeof(struct plain_regs_struct));
|
||||
if (ictx->regs_arg == NULL)
|
||||
goto err;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,16 @@
|
|||
#define xzalloc(size) __xalloc(calloc, size, 1, size)
|
||||
#define xrealloc(p, size) __xalloc(realloc, size, p, size)
|
||||
|
||||
#define xmemalign(align, size) \
|
||||
({ \
|
||||
void *___p = NULL; \
|
||||
int ___err = posix_memalign(&___p, align, size); \
|
||||
if (___err) \
|
||||
pr_err("%s: Can't allocate %li bytes aligned to %li\n", \
|
||||
__func__, (long)(size), (long)(align)); \
|
||||
___p; \
|
||||
})
|
||||
|
||||
#define xfree(p) free(p)
|
||||
|
||||
#define xrealloc_safe(pptr, size) \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue