]> xenbits.xensource.com Git - people/tklengyel/xen.git/commitdiff
xen/tasklet: CFI hardening
authorAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 28 Oct 2021 09:58:37 +0000 (10:58 +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.

The function pointer cast in hvm_vcpu_initialise() is undefined behaviour.

While it happens to function correctly, it is not compatible with control flow
typechecking, so introduce a new hvm_assert_evtchn_irq_tasklet() to handle the
parameter type conversion in a legal way.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
13 files changed:
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/vlapic.c
xen/arch/x86/include/asm/shadow.h
xen/arch/x86/mm/shadow/common.c
xen/common/domain.c
xen/common/keyhandler.c
xen/common/livepatch.c
xen/common/stop_machine.c
xen/common/trace.c
xen/drivers/char/console.c
xen/drivers/passthrough/amd/iommu_guest.c
xen/drivers/passthrough/amd/iommu_init.c
xen/drivers/passthrough/vtd/iommu.c

index 0a193530680aa396c09fa990967f099a8d7c3bf8..5ec10f30803e6e1d1973a3beaa326588cf7a4643 100644 (file)
@@ -1528,6 +1528,11 @@ static int __init cf_check hvm_register_CPU_save_and_restore(void)
 }
 __initcall(hvm_register_CPU_save_and_restore);
 
+static void cf_check hvm_assert_evtchn_irq_tasklet(void *v)
+{
+    hvm_assert_evtchn_irq(v);
+}
+
 int hvm_vcpu_initialise(struct vcpu *v)
 {
     int rc;
@@ -1552,7 +1557,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
         goto fail3;
 
     softirq_tasklet_init(&v->arch.hvm.assert_evtchn_irq_tasklet,
-                         (void (*)(void *))hvm_assert_evtchn_irq, v);
+                         hvm_assert_evtchn_irq_tasklet, v);
 
     v->arch.hvm.inject_event.vector = HVM_EVENT_VECTOR_UNSET;
 
index b8c84458ffdc7c41c1a0d09893a6f5b41ea85229..fe375912bef16b2dbb126e03a3e0c6157de668ad 100644 (file)
@@ -312,7 +312,7 @@ static void vlapic_init_sipi_one(struct vcpu *target, uint32_t icr)
     vcpu_unpause(target);
 }
 
-static void vlapic_init_sipi_action(void *data)
+static void cf_check vlapic_init_sipi_action(void *data)
 {
     struct vcpu *origin = data;
     uint32_t icr = vcpu_vlapic(origin)->init_sipi.icr;
index e25f9604d896d1f9b3794d70885cf8bf05827340..7ef76cc0635b84caf63857766de5816ac875658a 100644 (file)
@@ -233,7 +233,7 @@ static inline bool pv_l1tf_check_l4e(struct domain *d, l4_pgentry_t l4e)
     return pv_l1tf_check_pte(d, 4, l4e.l4);
 }
 
-void pv_l1tf_tasklet(void *data);
+void cf_check pv_l1tf_tasklet(void *data);
 
 static inline void pv_l1tf_domain_init(struct domain *d)
 {
index b8730a9441ce6c083d4bcfe370773938f5b0a4d3..fb370af90b5cb473521c102a74070b5da38d043f 100644 (file)
@@ -3242,7 +3242,7 @@ void shadow_audit_tables(struct vcpu *v)
 
 #ifdef CONFIG_PV
 
-void pv_l1tf_tasklet(void *data)
+void cf_check pv_l1tf_tasklet(void *data)
 {
     struct domain *d = data;
 
index c5716cd72f63132834c5343c2a5c31b3faeaf19d..f3d06df76c33199724a4b24bbd93c1690b289a81 100644 (file)
@@ -1820,7 +1820,7 @@ struct migrate_info {
 
 static DEFINE_PER_CPU(struct migrate_info *, continue_info);
 
-static void continue_hypercall_tasklet_handler(void *data)
+static void cf_check continue_hypercall_tasklet_handler(void *data)
 {
     struct migrate_info *info = data;
     struct vcpu *v = info->vcpu;
index 2c916d528ab21dda128a43c8cb56794de803edf0..b568484ca62cb96bd729e7972a8f492fdce30eac 100644 (file)
@@ -73,7 +73,7 @@ static struct keyhandler {
 #undef KEYHANDLER
 };
 
-static void keypress_action(void *unused)
+static void cf_check keypress_action(void *unused)
 {
     handle_keypress(keypress_key, NULL);
 }
@@ -206,7 +206,7 @@ static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
 
 static DECLARE_TASKLET(dump_hwdom_tasklet, NULL, NULL);
 
-static void dump_hwdom_action(void *data)
+static void cf_check dump_hwdom_action(void *data)
 {
     struct vcpu *v = data;
 
@@ -437,7 +437,7 @@ static void read_clocks(unsigned char key)
            maxdif_cycles, sumdif_cycles/count, count, dif_cycles);
 }
 
-static void run_all_nonirq_keyhandlers(void *unused)
+static void cf_check run_all_nonirq_keyhandlers(void *unused)
 {
     /* Fire all the non-IRQ-context diagnostic keyhandlers */
     struct keyhandler *h;
index 701efd87a17350cbcd3917d2cf9142f2b60aee50..4e1c29ab78795de28b3308e0430694885c449fb7 100644 (file)
@@ -1591,7 +1591,7 @@ static int schedule_work(struct payload *data, uint32_t cmd, uint32_t timeout)
     return 0;
 }
 
-static void tasklet_fn(void *unused)
+static void cf_check tasklet_fn(void *unused)
 {
     this_cpu(work_to_do) = 1;
 }
index a122bd4afe09c2e006cf3831dad156e6b7a727fc..3adbe380de965d7e11ff0692fe707a1803c1d22a 100644 (file)
@@ -141,7 +141,7 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu)
     return ret;
 }
 
-static void stopmachine_action(void *data)
+static void cf_check stopmachine_action(void *data)
 {
     unsigned int cpu = (unsigned long)data;
     enum stopmachine_state state = STOPMACHINE_START;
index b5358508f80482fa0c3eb20b9d31119f570dcd6c..a7c092fcbbe947221278e221938f5f155c7dc444 100644 (file)
@@ -663,7 +663,7 @@ static inline void insert_lost_records(struct t_buf *buf)
  * Notification is performed in qtasklet to avoid deadlocks with contexts
  * which __trace_var() may be called from (e.g., scheduler critical regions).
  */
-static void trace_notify_dom0(void *unused)
+static void cf_check trace_notify_dom0(void *unused)
 {
     send_global_virq(VIRQ_TBUF);
 }
index 4694be83db4531af9e020e6998cecb189dc953bf..d74b65f6bf231336e48775e5848654681517b0bf 100644 (file)
@@ -574,7 +574,7 @@ static void serial_rx(char c, struct cpu_user_regs *regs)
     __serial_rx(c, regs);
 }
 
-static void notify_dom0_con_ring(void *unused)
+static void cf_check notify_dom0_con_ring(void *unused)
 {
     send_global_virq(VIRQ_CON_RING);
 }
index 85828490ffee447c689ea1304fcf132137823242..361ff864d846f2570ec3b1ac2c5693b36cc79db0 100644 (file)
@@ -456,7 +456,7 @@ static int do_invalidate_dte(struct domain *d, cmd_entry_t *cmd)
     return 0;
 }
 
-static void guest_iommu_process_command(void *data)
+static void cf_check guest_iommu_process_command(void *data)
 {
     unsigned long opcode, tail, head, cmd_mfn;
     cmd_entry_t *cmd;
index f1ed75558227088dd8159f80860e0f0e989d9055..34a9e49f1c5a7e7fa6f58a23c4bed7749b5edc1c 100644 (file)
@@ -26,7 +26,7 @@
 static int __initdata nr_amd_iommus;
 static bool __initdata pci_init;
 
-static void do_amd_iommu_irq(void *data);
+static void cf_check do_amd_iommu_irq(void *data);
 static DECLARE_SOFTIRQ_TASKLET(amd_iommu_irq_tasklet, do_amd_iommu_irq, NULL);
 
 unsigned int __read_mostly amd_iommu_acpi_info;
@@ -692,7 +692,7 @@ static void iommu_check_ppr_log(struct amd_iommu *iommu)
     spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-static void do_amd_iommu_irq(void *unused)
+static void cf_check do_amd_iommu_irq(void *unused)
 {
     struct amd_iommu *iommu;
 
index 6ed32922c453adba667d5c835912747a22d1b793..42181e12be5a2d9e3e189d06d8f445daec33d96a 100644 (file)
@@ -1049,7 +1049,7 @@ clear_overflow:
     }
 }
 
-static void do_iommu_page_fault(void *unused)
+static void cf_check do_iommu_page_fault(void *unused)
 {
     struct acpi_drhd_unit *drhd;