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`.

Reply via email to