x86/apic: CFI hardening
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 28 Oct 2021 13:05:05 +0000 (14:05 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 23 Feb 2022 15:33:43 +0000 (15:33 +0000)
Control Flow Integrity schemes use toolchain and optionally hardware support
to help protect against call/jump/return oriented programming attacks.

Use cf_check to annotate function pointer targets for the toolchain.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/genapic/bigsmp.c
xen/arch/x86/genapic/delivery.c
xen/arch/x86/genapic/x2apic.c
xen/arch/x86/include/asm/genapic.h
xen/arch/x86/smp.c

index b9d976e8abf2023f2f61bb169c1338a114c11e7d..2000383ab0bf07341b2dda5494aecec52a444413 100644 (file)
@@ -10,7 +10,7 @@
 #include <xen/dmi.h>
 #include <asm/io_apic.h>
 
-static __init int force_bigsmp(const struct dmi_system_id *d)
+static int __init cf_check force_bigsmp(const struct dmi_system_id *d)
 {
        printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
        def_to_bigsmp = true;
@@ -27,7 +27,7 @@ static const struct dmi_system_id __initconstrel bigsmp_dmi_table[] = {
 };
 
 
-static __init int probe_bigsmp(void)
+static int __init cf_check probe_bigsmp(void)
 { 
        /*
         * We don't implement cluster mode, so force use of
index 548c33f282dd399cef58a31d5c7f35f2a1a1e5fb..d1f99bf6834a52865f6c66e81fd5a9594ab3b8c1 100644 (file)
@@ -9,7 +9,7 @@
  * LOGICAL FLAT DELIVERY MODE (multicast via bitmask to <= 8 logical APIC IDs).
  */
 
-void init_apic_ldr_flat(void)
+void cf_check init_apic_ldr_flat(void)
 {
        unsigned long val;
 
@@ -19,12 +19,12 @@ void init_apic_ldr_flat(void)
        apic_write(APIC_LDR, val);
 }
 
-const cpumask_t *vector_allocation_cpumask_flat(int cpu)
+const cpumask_t *cf_check vector_allocation_cpumask_flat(int cpu)
 {
        return &cpu_online_map;
 } 
 
-unsigned int cpu_mask_to_apicid_flat(const cpumask_t *cpumask)
+unsigned int cf_check cpu_mask_to_apicid_flat(const cpumask_t *cpumask)
 {
        return cpumask_bits(cpumask)[0]&0xFF;
 }
@@ -33,17 +33,17 @@ unsigned int cpu_mask_to_apicid_flat(const cpumask_t *cpumask)
  * PHYSICAL DELIVERY MODE (unicast to physical APIC IDs).
  */
 
-void init_apic_ldr_phys(void)
+void cf_check init_apic_ldr_phys(void)
 {
        /* We only deliver in phys mode - no setup needed. */
 }
 
-const cpumask_t *vector_allocation_cpumask_phys(int cpu)
+const cpumask_t *cf_check vector_allocation_cpumask_phys(int cpu)
 {
        return cpumask_of(cpu);
 }
 
-unsigned int cpu_mask_to_apicid_phys(const cpumask_t *cpumask)
+unsigned int cf_check cpu_mask_to_apicid_phys(const cpumask_t *cpumask)
 {
        /* As we are using single CPU as destination, pick only one CPU here */
        return cpu_physical_id(cpumask_any(cpumask));
index bd44bb7539953087bb26a348f235da5907ae1782..de5032f2020ac65cc35219d693864ef587dc255b 100644 (file)
@@ -38,7 +38,7 @@ static inline u32 x2apic_cluster(unsigned int cpu)
     return per_cpu(cpu_2_logical_apicid, cpu) >> 16;
 }
 
-static void init_apic_ldr_x2apic_cluster(void)
+static void cf_check init_apic_ldr_x2apic_cluster(void)
 {
     unsigned int cpu, this_cpu = smp_processor_id();
 
@@ -74,12 +74,14 @@ static void init_apic_ldr_x2apic_cluster(void)
     cpumask_set_cpu(this_cpu, per_cpu(cluster_cpus, this_cpu));
 }
 
-static const cpumask_t *vector_allocation_cpumask_x2apic_cluster(int cpu)
+static const cpumask_t *cf_check vector_allocation_cpumask_x2apic_cluster(
+    int cpu)
 {
     return per_cpu(cluster_cpus, cpu);
 }
 
-static unsigned int cpu_mask_to_apicid_x2apic_cluster(const cpumask_t *cpumask)
+static unsigned int cf_check cpu_mask_to_apicid_x2apic_cluster(
+    const cpumask_t *cpumask)
 {
     unsigned int cpu = cpumask_any(cpumask);
     unsigned int dest = per_cpu(cpu_2_logical_apicid, cpu);
@@ -92,12 +94,13 @@ static unsigned int cpu_mask_to_apicid_x2apic_cluster(const cpumask_t *cpumask)
     return dest;
 }
 
-static void send_IPI_self_x2apic(uint8_t vector)
+static void cf_check send_IPI_self_x2apic(uint8_t vector)
 {
     apic_wrmsr(APIC_SELF_IPI, vector);
 }
 
-static void send_IPI_mask_x2apic_phys(const cpumask_t *cpumask, int vector)
+static void cf_check send_IPI_mask_x2apic_phys(
+    const cpumask_t *cpumask, int vector)
 {
     unsigned int cpu;
     unsigned long flags;
@@ -130,7 +133,8 @@ static void send_IPI_mask_x2apic_phys(const cpumask_t *cpumask, int vector)
     local_irq_restore(flags);
 }
 
-static void send_IPI_mask_x2apic_cluster(const cpumask_t *cpumask, int vector)
+static void cf_check send_IPI_mask_x2apic_cluster(
+    const cpumask_t *cpumask, int vector)
 {
     unsigned int cpu = smp_processor_id();
     cpumask_t *ipimask = per_cpu(scratch_mask, cpu);
index 51a65d3e0f0c7928d0478b30adbc455321c9573c..beeaddf19daa6e338923e6a539f21a9f704bb0da 100644 (file)
@@ -39,12 +39,12 @@ extern struct genapic genapic;
 extern const struct genapic apic_default;
 extern const struct genapic apic_bigsmp;
 
-void send_IPI_self_legacy(uint8_t vector);
+void cf_check send_IPI_self_legacy(uint8_t vector);
 
-void init_apic_ldr_flat(void);
-unsigned int cpu_mask_to_apicid_flat(const cpumask_t *cpumask);
-void send_IPI_mask_flat(const cpumask_t *mask, int vector);
-const cpumask_t *vector_allocation_cpumask_flat(int cpu);
+void cf_check init_apic_ldr_flat(void);
+unsigned int cf_check cpu_mask_to_apicid_flat(const cpumask_t *cpumask);
+void cf_check send_IPI_mask_flat(const cpumask_t *mask, int vector);
+const cpumask_t *cf_check vector_allocation_cpumask_flat(int cpu);
 #define GENAPIC_FLAT \
        .int_delivery_mode = dest_LowestPrio, \
        .int_dest_mode = 1 /* logical delivery */, \
@@ -54,10 +54,10 @@ const cpumask_t *vector_allocation_cpumask_flat(int cpu);
        .send_IPI_mask = send_IPI_mask_flat, \
        .send_IPI_self = send_IPI_self_legacy
 
-void init_apic_ldr_phys(void);
-unsigned int cpu_mask_to_apicid_phys(const cpumask_t *cpumask);
-void send_IPI_mask_phys(const cpumask_t *mask, int vector);
-const cpumask_t *vector_allocation_cpumask_phys(int cpu);
+void cf_check init_apic_ldr_phys(void);
+unsigned int cf_check cpu_mask_to_apicid_phys(const cpumask_t *cpumask);
+void cf_check send_IPI_mask_phys(const cpumask_t *mask, int vector);
+const cpumask_t *cf_check vector_allocation_cpumask_phys(int cpu);
 #define GENAPIC_PHYS \
        .int_delivery_mode = dest_Fixed, \
        .int_dest_mode = 0 /* physical delivery */, \
index 33748e629a21d417fe837a82202520eb9cf08877..0a02086966c0009469e2a8663f3a00e2c6cf5124 100644 (file)
@@ -161,13 +161,13 @@ void send_IPI_self(int vector)
  * The following functions deal with sending IPIs between CPUs.
  */
 
-void send_IPI_self_legacy(uint8_t vector)
+void cf_check send_IPI_self_legacy(uint8_t vector)
 {
     /* NMI continuation handling relies on using a shorthand here. */
     send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
 }
 
-void send_IPI_mask_flat(const cpumask_t *cpumask, int vector)
+void cf_check send_IPI_mask_flat(const cpumask_t *cpumask, int vector)
 {
     unsigned long mask = cpumask_bits(cpumask)[0];
     unsigned long cfg;
@@ -204,7 +204,7 @@ void send_IPI_mask_flat(const cpumask_t *cpumask, int vector)
     local_irq_restore(flags);
 }
 
-void send_IPI_mask_phys(const cpumask_t *mask, int vector)
+void cf_check send_IPI_mask_phys(const cpumask_t *mask, int vector)
 {
     unsigned long cfg, flags;
     unsigned int query_cpu;