x86: verify function type (and maybe attribute) in switch_stack_and_jump()
authorJan Beulich <jbeulich@suse.com>
Tue, 22 Dec 2020 07:57:19 +0000 (08:57 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 22 Dec 2020 07:57:19 +0000 (08:57 +0100)
It is imperative that the functions passed here are taking no arguments,
return no values, and don't return in the first place. While the type
can be checked uniformly, the attribute check is limited to gcc 9 and
newer (no clang support for this so far afaict).

Note that I didn't want to have the "true" fallback "implementation" of
__builtin_has_attribute(..., __noreturn__) generally available, as
"true" may not be a suitable fallback in other cases.

Note further that the noreturn addition to startup_cpu_idle_loop()'s
declaration requires adding unreachable() to Arm's
switch_stack_and_jump(), or else the build would break. I suppose this
should have been there already.

For vmx_asm_do_vmentry() along with adding the attribute, also restrict
its scope.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Wei Liu <wl@xen.org>
Acked-by: Julien Grall <jgrall@amazon.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/setup.c
xen/include/asm-arm/current.h
xen/include/asm-x86/current.h
xen/include/asm-x86/hvm/vmx/vmx.h
xen/include/xen/sched.h

index d90627d4f77cd6cca00f9f64f5da5b5affa6cd88..0854fcfc1467604f1a69e59e9447b613a820a4d0 100644 (file)
@@ -63,7 +63,7 @@
 #include <asm/monitor.h>
 #include <asm/xstate.h>
 
-void svm_asm_do_resume(void);
+void noreturn svm_asm_do_resume(void);
 
 u32 svm_feature_flags;
 
index 1466064d0cc91f51f182f9c9e4571468e0c3e436..164535f8f09bbbe639962772fb2373c9ab5450a2 100644 (file)
@@ -1850,6 +1850,8 @@ void vmx_vmentry_failure(void)
     domain_crash(curr->domain);
 }
 
+void noreturn vmx_asm_do_vmentry(void);
+
 void vmx_do_resume(void)
 {
     struct vcpu *v = current;
index 1a2e5e41ab32271c94dc47e5392acf5f8a11183b..5cdb0f0f92c03bd6b011ab3c13167bd74f1a2929 100644 (file)
@@ -619,7 +619,7 @@ static inline bool using_2M_mapping(void)
            !l1_table_offset((unsigned long)__2M_rwdata_end);
 }
 
-static void noinline init_done(void)
+static void noreturn init_done(void)
 {
     void *va;
     unsigned long start, end;
index f71da9fab99fe21b714031a6e3ad670fdf673ac9..e7fbf535d2a3b1bc673f6c232daff5c60d8c55a9 100644 (file)
@@ -43,8 +43,10 @@ static inline struct cpu_info *get_cpu_info(void)
 
 #define guest_cpu_user_regs() (&get_cpu_info()->guest_cpu_user_regs)
 
-#define switch_stack_and_jump(stack, fn)                                \
-    asm volatile ("mov sp,%0; b " STR(fn) : : "r" (stack) : "memory" )
+#define switch_stack_and_jump(stack, fn) do {                           \
+    asm volatile ("mov sp,%0; b " STR(fn) : : "r" (stack) : "memory" ); \
+    unreachable();                                                      \
+} while ( false )
 
 #define reset_stack_and_jump(fn) switch_stack_and_jump(get_cpu_info(), fn)
 
index 231994a2453d0f264b2a76a6981bf42650b5aff4..5d690ce014ed51117828bd692b04e729e19f2a7a 100644 (file)
@@ -163,9 +163,18 @@ unsigned long get_stack_dump_bottom (unsigned long sp);
 # define SHADOW_STACK_WORK ""
 #endif
 
+#if __GNUC__ >= 9
+# define ssaj_has_attr_noreturn(fn) __builtin_has_attribute(fn, __noreturn__)
+#else
+/* Simply can't check the property with older gcc. */
+# define ssaj_has_attr_noreturn(fn) true
+#endif
+
 #define switch_stack_and_jump(fn, instr, constr)                        \
     ({                                                                  \
         unsigned int tmp;                                               \
+        (void)((fn) == (void (*)(void))NULL);                           \
+        BUILD_BUG_ON(!ssaj_has_attr_noreturn(fn));                      \
         __asm__ __volatile__ (                                          \
             SHADOW_STACK_WORK                                           \
             "mov %[stk], %%rsp;"                                        \
index 09ea0fa2cdf27426d6ec1cd235c462817852cb2e..534e9fc221a19b36d3ff17ca181da44b5386f562 100644 (file)
@@ -93,7 +93,6 @@ typedef enum {
 #define PI_xAPIC_NDST_MASK      0xFF00
 
 void vmx_asm_vmexit_handler(struct cpu_user_regs);
-void vmx_asm_do_vmentry(void);
 void vmx_intr_assist(void);
 void noreturn vmx_do_resume(void);
 void vmx_vlapic_msr_changed(struct vcpu *v);
index faf5fda36f9aae67533849bf7647ad52f34875b8..76af29e932dd87a7e962a12b840f1a2ad6c04c3d 100644 (file)
@@ -736,7 +736,7 @@ void sched_context_switched(struct vcpu *prev, struct vcpu *vnext);
 void continue_running(
     struct vcpu *same);
 
-void startup_cpu_idle_loop(void);
+void noreturn startup_cpu_idle_loop(void);
 extern void (*pm_idle) (void);
 extern void (*dead_idle) (void);