From: Andrew Cooper Date: Fri, 6 Nov 2020 18:53:39 +0000 (+0000) Subject: hypercall: Work around Clang code generation bug X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=848c3f2dd42711c4d9fc01839d6630c115daa22f;p=xtf.git hypercall: Work around Clang code generation bug _hypercall64_4() is mis-compiled by some versions of Clang (5 is ok, 9 and later not), in a way which breaks the XSA-286 PoC. Clang loses the association between argument 4 being in %r10 between the input "a" (_a4) and the output "=&r" (__ign4), so while the input is handled correctly, the clobber on the output is missed. In the XSA-286, PoC, this causes clang to hoist the setting of DOMID_SELF out of the loop, and the test subsequently to malfunction on debug versions of Xen which intentionally clobber the hypercall parameters. Rewrite the hypercall macros to a single "+r" parameter form, rather than dual input/output form, which causes all tested versions of Clang to set up %r10 on each loop iteration. Signed-off-by: Andrew Cooper --- diff --git a/arch/x86/include/arch/hypercall-x86_32.h b/arch/x86/include/arch/hypercall-x86_32.h index 9bb72ef..bf1d4f1 100644 --- a/arch/x86/include/arch/hypercall-x86_32.h +++ b/arch/x86/include/arch/hypercall-x86_32.h @@ -9,52 +9,49 @@ #define _hypercall32_1(type, hcall, a1) \ ({ \ - long __res, __ign1; \ + long _res = (long)(hcall), _a1 = (long)(a1); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=b" (__ign1) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)) \ + : "+a" (_res), "+b" (_a1) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #define _hypercall32_2(type, hcall, a1, a2) \ ({ \ - long __res, __ign1, __ign2; \ + long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=b" (__ign1), "=c" (__ign2) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)), "2" ((long)(a2)) \ + : "+a" (_res), "+b" (_a1), "+c" (_a2) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #define _hypercall32_3(type, hcall, a1, a2, a3) \ ({ \ - long __res, __ign1, __ign2, __ign3; \ + long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2), \ + _a3 = (long)(a3); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=b" (__ign1), "=c" (__ign2), "=d" (__ign3) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)) \ + : "+a" (_res), "+b" (_a1), "+c" (_a2), "+d" (_a3) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #define _hypercall32_4(type, hcall, a1, a2, a3, a4) \ ({ \ - long __res, __ign1, __ign2, __ign3, __ign4; \ + long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2), \ + _a3 = (long)(a3), _a4 = (long)(a4); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=b" (__ign1), "=c" (__ign2), "=d" (__ign3),\ - "=S" (__ign4) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)), \ - "4" ((long)(a4)) \ + : "+a" (_res), "+b" (_a1), "+c" (_a2), "+d" (_a3), \ + "+S" (_a4) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #endif /* XTF_X86_32_HYPERCALL_H */ diff --git a/arch/x86/include/arch/hypercall-x86_64.h b/arch/x86/include/arch/hypercall-x86_64.h index 885bd30..d6db99f 100644 --- a/arch/x86/include/arch/hypercall-x86_64.h +++ b/arch/x86/include/arch/hypercall-x86_64.h @@ -9,53 +9,50 @@ #define _hypercall64_1(type, hcall, a1) \ ({ \ - long __res, __ign1; \ + long _res = (long)(hcall), _a1 = (long)(a1); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=D" (__ign1) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)) \ + : "+a" (_res), "+D" (_a1) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #define _hypercall64_2(type, hcall, a1, a2) \ ({ \ - long __res, __ign1, __ign2; \ + long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=D" (__ign1), "=S" (__ign2) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)), "2" ((long)(a2)) \ + : "+a" (_res), "+D" (_a1), "+S" (_a2) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #define _hypercall64_3(type, hcall, a1, a2, a3) \ ({ \ - long __res, __ign1, __ign2, __ign3; \ + long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2), \ + _a3 = (long)(a3); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=D" (__ign1), "=S" (__ign2), "=d" (__ign3) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)) \ + : "+a" (_res), "+D" (_a1), "+S" (_a2), "+d" (_a3) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #define _hypercall64_4(type, hcall, a1, a2, a3, a4) \ ({ \ - long __res, __ign1, __ign2, __ign3, __ign4; \ - register long _a4 asm ("r10") = ((long)(a4)); \ + long _res = (long)(hcall), _a1 = (long)(a1), _a2 = (long)(a2), \ + _a3 = (long)(a3); \ + register long _a4 asm ("r10") = (long)(a4); \ asm volatile ( \ "call hypercall_page + %c[offset]" \ - : "=a" (__res), "=D" (__ign1), "=S" (__ign2), "=d" (__ign3),\ - "=&r" (__ign4) \ - : [offset] "i" (hcall * 32), \ - "1" ((long)(a1)), "2" ((long)(a2)), "3" ((long)(a3)), \ - "4" (_a4) \ + : "+a" (_res), "+D" (_a1), "+S" (_a2), "+d" (_a3), \ + "+r" (_a4) \ + : [offset] "i" (hcall * 32) \ : "memory" ); \ - (type)__res; \ + (type)_res; \ }) #endif /* XTF_X86_64_HYPERCALL_H */