https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128283
Bug ID: 128283
Summary: [x86] sgxintrin.h and pconfigintrin.h inline asm
wrappers miss "memory" clobber
Product: gcc
Version: 16.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: 220245569 at seu dot edu.cn
CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Target: x86_64-*-*, i?86-*-*
Summary
-------
In `gcc/config/i386/sgxintrin.h:42-112` and
`gcc/config/i386/pconfigintrin.h:44-53`,
all 13 `__encls_*` / `__enclu_*` / `__enclv_*` inline asm macros and both
`__pconfig_*` macros pass buffer/structure pointers in general-purpose
registers
(`%rbx`, `%rcx`, `%rdx`), but their clobber lists declare only `"cc"` (or
empty):
#define __enclu_bc(leaf, b, c, retval) \
__asm__ __volatile__ ("enclu\n\t" \
: "=a" (retval) \
: "a" (leaf), "b" (b), "c" (c) \
: "cc")
Because `"memory"` is omitted, GIMPLE dead-store elimination (`dse1`) deletes
stack stores initializing input structures (`SECINFO`, `PAGEINFO`,
`MKTME_KEY_PROGRAM`)
right before `ENCLU`/`PCONFIG`, and GIMPLE FRE/CSE constant-folds
post-instruction
reads from output buffers (such as SGX `EGETKEY` 128-bit keys) to `0`.
Reproducer
----------
$ cat trigger.c
#include <immintrin.h>
#include <stdint.h>
uint64_t derive_sgx_key(uint64_t *req_aligned) {
uint64_t key[2] __attribute__((aligned(16))) = {0, 0};
size_t d[3] = {(size_t)req_aligned, (size_t)key, 0};
_enclu_u32(1 /* EGETKEY */, d);
return key[0];
}
struct mktme_kp {
uint16_t keyid;
uint32_t ctrl;
uint8_t pad[186];
};
unsigned int program_mktme(uint16_t kid) {
struct mktme_kp kp = {.keyid = kid, .ctrl = 1};
size_t d[3] = {(size_t)&kp, 0, 0};
return _pconfig_u32(0 /* MKTME_KEY_PROGRAM */, d);
}
Compile flag: gcc -O2 -msgx -mpconfig -S trigger.c
$ cat trigger.s
derive_sgx_key:
pushq %rbx
movl $1, %eax
movq %rdi, %rbx
leaq -16(%rsp), %rcx
#APP
enclu
#NO_APP
xorl %eax, %eax # FRE folded key[0] to 0!
popq %rbx
ret
program_mktme:
pushq %rbx
xorl %ecx, %ecx
xorl %eax, %eax
movq %rcx, %rdx
subq $88, %rsp
leaq -120(%rsp), %rbx # DSE deleted all stores initializing
kp!
#APP
pconfig
#NO_APP
addq $88, %rsp
popq %rbx
ret
Suggested Fix
-------------
Add `"memory"` to the clobber list of all `__encls_*`, `__enclu_*`, and
`__enclv_*`
macros in `gcc/config/i386/sgxintrin.h` and `__pconfig_b` / `__pconfig_generic`
in `gcc/config/i386/pconfigintrin.h`.