diff --git a/sys/amd64/amd64/cfi.c b/sys/amd64/amd64/cfi.c new file mode 100644 --- /dev/null +++ b/sys/amd64/amd64/cfi.c @@ -0,0 +1,74 @@ +#include + +#include +#include + +#include +#include + +static int +regoff(int reg) +{ +#define _MATCH_REG(i, reg) \ + case i: \ + return (offsetof(struct trapframe, tf_ ## reg) / \ + sizeof(register_t)) + switch (reg) { + _MATCH_REG( 0, rax); + _MATCH_REG( 1, rcx); + _MATCH_REG( 2, rdx); + _MATCH_REG( 3, rbx); + _MATCH_REG( 4, rsp); /* SIB when mod != 3 */ + _MATCH_REG( 5, rbp); + _MATCH_REG( 6, rsi); + _MATCH_REG( 7, rdi); + _MATCH_REG( 8, r8); /* REX.R is set */ + _MATCH_REG( 9, r9); + _MATCH_REG(10, r10); + _MATCH_REG(11, r11); + _MATCH_REG(12, r12); + _MATCH_REG(13, r13); + _MATCH_REG(14, r14); + _MATCH_REG(15, r15); + } +#undef _MATCH_REG + return (0); +} + + +bool +decode_cfi(struct trapframe *tf, register_t *addr, uint32_t *type) { + unsigned char buffer[13]; + + strlcpy(buffer, (char *)(tf->tf_rip - 12), sizeof(buffer)); + /* + * clang generates following instructions: + * + * mov $typeid, %reg + * add $callee-16, %reg + * je .Lcorrect + * ud2 + * .Lcorrect + * + * What we do is to compare if the previous context is trigger by mov(0xba) and following with one add(0x03), + * if it is, we can identified it maybe CFI fault + */ + + + if(buffer[1] != 0xba) + return (false); + + if(buffer[7] != 0x03) + return (false); + + if(buffer[7] != 0x03) + return (false); + + *type = *((uint32_t *)(buffer + 2)); + + // Decode register(prefix & REX.R) | (MODRM.reg(3bit)) + *addr = ((register_t *)tf)[regoff((((buffer[0] >> 2) & 0x1) << 3) | ((buffer[2] >> 3) & 0x7))]; + return (true); +} + + diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -440,6 +441,14 @@ (void)trap_pfault(frame, false, NULL, NULL); return; + case T_PRIVINFLT: + /* Triggered by ud2 with kCFI enabled */ + #ifdef KCFI + if(cfi_handler(frame)) + return; + #endif + break; + case T_DNA: if (PCB_USER_FPU(td->td_pcb)) panic("Unregistered use of FPU in kernel"); @@ -936,7 +945,6 @@ frame->tf_r11, frame->tf_r12); printf("r13: %016lx r14: %016lx r15: %016lx\n", frame->tf_r13, frame->tf_r14, frame->tf_r15); - #ifdef KDB if (debugger_on_trap) { kdb_why = KDB_WHY_TRAP; diff --git a/sys/amd64/include/cfi.h b/sys/amd64/include/cfi.h new file mode 100644 --- /dev/null +++ b/sys/amd64/include/cfi.h @@ -0,0 +1,14 @@ +#ifndef _MACHINE_CFI_H +#define _MACHINE_CFI_H + +#include + + +#include +#include + + +bool +decode_cfi(struct trapframe *, register_t *, uint32_t *); + +#endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -345,21 +345,26 @@ { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, }; -static void -dtrace_nullop(void) -{} +#define DEFINE_NULLOP_HANDLER(name, ...) \ + static void name(__VA_ARGS__) \ + { \ + } + +DEFINE_NULLOP_HANDLER(dtrace_provide_handler, void *_1, dtrace_probedesc_t *_2); +DEFINE_NULLOP_HANDLER(dtrace_provide_module_handler, void *_1, modctl_t *_2); +DEFINE_NULLOP_HANDLER(dtrace_vpdtid_vp_handler, void *_1, dtrace_id_t _2, void *_3); static dtrace_pops_t dtrace_provider_ops = { - .dtps_provide = (void (*)(void *, dtrace_probedesc_t *))dtrace_nullop, - .dtps_provide_module = (void (*)(void *, modctl_t *))dtrace_nullop, - .dtps_enable = (void (*)(void *, dtrace_id_t, void *))dtrace_nullop, - .dtps_disable = (void (*)(void *, dtrace_id_t, void *))dtrace_nullop, - .dtps_suspend = (void (*)(void *, dtrace_id_t, void *))dtrace_nullop, - .dtps_resume = (void (*)(void *, dtrace_id_t, void *))dtrace_nullop, + .dtps_provide = dtrace_provide_handler, + .dtps_provide_module = dtrace_provide_module_handler, + .dtps_enable = dtrace_vpdtid_vp_handler, + .dtps_disable = dtrace_vpdtid_vp_handler, + .dtps_suspend = dtrace_vpdtid_vp_handler, + .dtps_resume = dtrace_vpdtid_vp_handler, .dtps_getargdesc = NULL, .dtps_getargval = NULL, .dtps_usermode = NULL, - .dtps_destroy = (void (*)(void *, dtrace_id_t, void *))dtrace_nullop, + .dtps_destroy = dtrace_vpdtid_vp_handler, }; static dtrace_id_t dtrace_probeid_begin; /* special BEGIN probe */ @@ -8783,21 +8788,21 @@ if (pops->dtps_provide == NULL) { ASSERT(pops->dtps_provide_module != NULL); provider->dtpv_pops.dtps_provide = - (void (*)(void *, dtrace_probedesc_t *))dtrace_nullop; + dtrace_provide_handler; } if (pops->dtps_provide_module == NULL) { ASSERT(pops->dtps_provide != NULL); provider->dtpv_pops.dtps_provide_module = - (void (*)(void *, modctl_t *))dtrace_nullop; + dtrace_provide_module_handler; } if (pops->dtps_suspend == NULL) { ASSERT(pops->dtps_resume == NULL); provider->dtpv_pops.dtps_suspend = - (void (*)(void *, dtrace_id_t, void *))dtrace_nullop; + dtrace_vpdtid_vp_handler; provider->dtpv_pops.dtps_resume = - (void (*)(void *, dtrace_id_t, void *))dtrace_nullop; + dtrace_vpdtid_vp_handler; } provider->dtpv_arg = arg; @@ -8864,8 +8869,7 @@ int i, self = 0, noreap = 0; dtrace_probe_t *probe, *first = NULL; - if (old->dtpv_pops.dtps_enable == - (void (*)(void *, dtrace_id_t, void *))dtrace_nullop) { + if (old->dtpv_pops.dtps_enable == dtrace_vpdtid_vp_handler) { /* * If DTrace itself is the provider, we're called with locks * already held. @@ -9043,8 +9047,7 @@ { dtrace_provider_t *pvp = (dtrace_provider_t *)id; - ASSERT(pvp->dtpv_pops.dtps_enable != - (void (*)(void *, dtrace_id_t, void *))dtrace_nullop); + ASSERT(pvp->dtpv_pops.dtps_enable != dtrace_vpdtid_vp_handler); mutex_enter(&dtrace_provider_lock); mutex_enter(&dtrace_lock); @@ -9084,8 +9087,7 @@ /* * Make sure this isn't the dtrace provider itself. */ - ASSERT(prov->dtpv_pops.dtps_enable != - (void (*)(void *, dtrace_id_t, void *))dtrace_nullop); + ASSERT(prov->dtpv_pops.dtps_enable != dtrace_vpdtid_vp_handler); mutex_enter(&dtrace_provider_lock); mutex_enter(&dtrace_lock); diff --git a/sys/compat/linuxkpi/common/include/linux/module.h b/sys/compat/linuxkpi/common/include/linux/module.h --- a/sys/compat/linuxkpi/common/include/linux/module.h +++ b/sys/compat/linuxkpi/common/include/linux/module.h @@ -61,9 +61,11 @@ #define SI_SUB_OFED_MODINIT (SI_SUB_ROOT_CONF - 1) #include +#include static inline void _module_run(void *arg) +__NOCFI { void (*fn)(void); #ifdef OFED_DEBUG_INIT diff --git a/sys/conf/Makefile.amd64 b/sys/conf/Makefile.amd64 --- a/sys/conf/Makefile.amd64 +++ b/sys/conf/Makefile.amd64 @@ -35,6 +35,10 @@ CFLAGS+= -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer .endif +.if !empty(KCFI_ENABLED) +CFLAGS+= -fsanitize=kcfi +.endif + %BEFORE_DEPEND %OBJS diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -3877,6 +3877,8 @@ kern/subr_bus_dma.c standard kern/subr_bufring.c standard kern/subr_capability.c standard +kern/subr_cfi.c optional kcfi \ + compile-with "${NORMAL_C:N-fsanitize*:N-fstack-protector*}" kern/subr_clock.c standard kern/subr_compressor.c standard \ compile-with "${NORMAL_C} -I$S/contrib/zstd/lib/freebsd" diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -64,6 +64,7 @@ amd64/amd64/bios.c standard amd64/amd64/bpf_jit_machdep.c optional bpf_jitter amd64/amd64/copyout.c standard +amd64/amd64/cfi.c optional kcfi amd64/amd64/cpu_switch.S standard amd64/amd64/db_disasm.c optional ddb amd64/amd64/db_interface.c optional ddb diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk --- a/sys/conf/kern.mk +++ b/sys/conf/kern.mk @@ -145,7 +145,7 @@ CFLAGS += -mbranch-protection=standard INLINE_LIMIT?= 8000 .endif - +CFLAGS += -fsanitize=kcfi # # For RISC-V we specify the soft-float ABI (lp64) to avoid the use of floating # point registers within the kernel. However, we include the F and D extensions diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -37,6 +37,10 @@ MKMODULESENV+= KCSAN_ENABLED="yes" .endif +.if !empty(KCFI_ENABLED) +MKMODULESENV+= KCFI_ENABLED="yes" +.endif + .if defined(SAN_CFLAGS) MKMODULESENV+= SAN_CFLAGS="${SAN_CFLAGS}" .endif diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -91,7 +91,7 @@ COMPAT_FREEBSD32_ENABLED!= grep COMPAT_FREEBSD32 opt_global.h || true ; echo -KASAN_ENABLED!= grep KASAN opt_global.h || true ; echo +KASAN_ENABLED!= grep KASAN opt_global.h || true ; echo .if !empty(KASAN_ENABLED) SAN_CFLAGS+= -DSAN_NEEDS_INTERCEPTORS -DSAN_INTERCEPTOR_PREFIX=kasan \ -fsanitize=kernel-address \ @@ -102,6 +102,11 @@ -mllvm -asan-instrumentation-with-call-threshold=0 \ -mllvm -asan-instrument-byval=false +KCFI_ENABLED!= grep KCFI opt_global.h || true ; echo +.if !empty(KCFI_ENABLED) +SAN_CFLAGS+= -fsanitize=kcfi +.endif + .if ${MACHINE_CPUARCH} == "aarch64" # KASAN/ARM64 TODO: -asan-mapping-offset is calculated from: # (VM_KERNEL_MIN_ADDRESS >> KASAN_SHADOW_SCALE_SHIFT) + $offset = KASAN_MIN_ADDRESS diff --git a/sys/conf/options b/sys/conf/options --- a/sys/conf/options +++ b/sys/conf/options @@ -252,6 +252,7 @@ # Sanitizers COVERAGE opt_global.h KASAN opt_global.h +KCFI opt_global.h KCOV KCSAN opt_global.h KMSAN opt_global.h diff --git a/sys/dev/acpica/acpi_if.m b/sys/dev/acpica/acpi_if.m --- a/sys/dev/acpica/acpi_if.m +++ b/sys/dev/acpica/acpi_if.m @@ -58,7 +58,7 @@ }; # -# Default implementation for acpi_id_probe(). +# Default implementation for some codes. # CODE { static int @@ -67,6 +67,61 @@ { return (ENXIO); } + + static ACPI_STATUS + null_evaluate_object(device_t bus, device_t dev, ACPI_STRING pathname, ACPI_OBJECT_LIST *parameters, + ACPI_BUFFER *ret) + { + return_ACPI_STATUS (AE_NOT_FOUND); + } + + static ACPI_STATUS + null_get_property(device_t bus, device_t dev, ACPI_STRING propname, const ACPI_OBJECT **value) + { + return_ACPI_STATUS (AE_NOT_FOUND); + } + + static int + null_pwr_for_sleep(device_t bus, device_t dev, int *dstate) + { + return (ENXIO); + } + + static ACPI_STATUS + null_scan_children(device_t bus, device_t dev, int max_depth, acpi_scan_cb_t user_fn, void *arg) + { + return_ACPI_STATUS (AE_NOT_FOUND); + } + + static int + null_get_features(driver_t *driver, u_int *features) + { + return (ENXIO); + } + + static int + null_ec_read(device_t dev, u_int addr, UINT64 *val, int width) + { + return (ENXIO); + } + + static int + null_ec_write(device_t dev, u_int addr, UINT64 val, int witdh) + { + return (ENXIO); + } + + static int + null_batt_get_info(device_t dev, void *bix, size_t len) + { + return (ENXIO); + } + + static int + null_batt_get_status(device_t dev, struct acpi_bst *bst) + { + return (ENXIO); + } }; # @@ -118,7 +173,7 @@ ACPI_STRING pathname; ACPI_OBJECT_LIST *parameters; ACPI_BUFFER *ret; -}; +} DEFAULT null_evaluate_object; # # Get property value from Device Specific Data @@ -139,7 +194,7 @@ device_t dev; ACPI_STRING propname; const ACPI_OBJECT **value; -}; +} DEFAULT null_get_property; # # Get the highest power state (D0-D3) that is usable for a device when @@ -158,7 +213,7 @@ device_t bus; device_t dev; int *dstate; -}; +} DEFAULT null_pwr_for_sleep; # # Rescan a subtree and optionally reattach devices to handles. Users @@ -185,7 +240,7 @@ int max_depth; acpi_scan_cb_t user_fn; void *arg; -}; +} DEFAULT null_scan_children; # # Query a given driver for its supported feature(s). This should be @@ -198,7 +253,7 @@ STATICMETHOD int get_features { driver_t *driver; u_int *features; -}; +} DEFAULT null_get_features; # # Read embedded controller (EC) address space @@ -213,7 +268,7 @@ u_int addr; UINT64 *val; int width; -}; +} DEFAULT null_ec_read; # # Write embedded controller (EC) address space @@ -228,7 +283,7 @@ u_int addr; UINT64 val; int width; -}; +} DEFAULT null_ec_write; # # Get battery information (_BIF or _BIX format) @@ -241,7 +296,7 @@ device_t dev; void *bix; size_t len; -}; +} DEFAULT null_batt_get_info; # # Get battery status (_BST format) @@ -252,4 +307,4 @@ METHOD int batt_get_status { device_t dev; struct acpi_bst *bst; -}; +} DEFAULT null_batt_get_status; diff --git a/sys/dev/pci/pci_dw_if.m b/sys/dev/pci/pci_dw_if.m --- a/sys/dev/pci/pci_dw_if.m +++ b/sys/dev/pci/pci_dw_if.m @@ -30,6 +30,31 @@ INTERFACE pci_dw; +CODE { + static uint32_t + null_dbi_read(device_t dev, u_int reg, int witdh) + { + return (ENXIO); + } + + static void + null_dbi_write(device_t dev, u_int reg, uint32_t value, int width) + { + } + + static int + null_set_link(device_t dev, bool start) + { + return (ENXIO); + } + + static int + null_get_link(device_t dev, bool *status) + { + return (ENXIO); + } +}; + /** * Read from dbi space. * The reg argument is a byte offset into dbi space. @@ -40,7 +65,7 @@ device_t dev; u_int reg; int width; -}; +} DEFAULT null_dbi_read; /** * Write to dbi space. @@ -53,7 +78,7 @@ u_int reg; uint32_t value; int width; -}; +} DEFAULT null_dbi_write; /** * Start or stop link @@ -61,7 +86,7 @@ METHOD int set_link{ device_t dev; bool start; -}; +} DEFAULT null_set_link; /** * Query link status (up/down) @@ -69,4 +94,4 @@ METHOD int get_link{ device_t dev; bool *status; -}; +} DEFAULT null_get_link; diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -50,6 +50,179 @@ device_printf(bus, "PCI_IOV not implemented on this bus.\n"); return (NULL); } + + static u_int32_t + null_read_config(device_t dev, device_t child, int reg, int width) + { + return (ENXIO); + } + + static void + null_write_config(device_t dev, device_t child, int reg, u_int32_t val, int width) + { + } + + static int + null_get_powerstate(device_t dev, device_t child) + { + return (ENXIO); + } + + static int + null_set_powerstate(device_t dev, device_t child, int state) + { + return (ENXIO); + } + + static int + null_get_vpd_ident(device_t dev, device_t child, const char **identptr) + { + return (ENXIO); + } + + static int + null_get_vpd_readonly(device_t dev, device_t child, const char *kw, const char **vptr) + { + return (ENXIO); + } + + static int + null_enable_busmaster(device_t dev, device_t child) + { + return (ENXIO); + } + + static int + null_disable_busmaster(device_t dev, device_t child) + { + return (ENXIO); + } + + static int + null_enable_io(device_t dev, device_t child, int space) + { + return (ENXIO); + } + + static int + null_disable_io(device_t dev, device_t child, int space) + { + return (ENXIO); + } + + static int + null_assign_interrupt(device_t dev, device_t child) + { + return (ENXIO); + } + + static int + null_find_cap(device_t dev, device_t child, int capability, int *capreg) + { + return (ENXIO); + } + + static int + null_find_next_cap(device_t dev, device_t child, int capability, int start, int *capreg) + { + return (ENXIO); + } + + static int + null_find_extcap(device_t dev, device_t child, int capability, int *capreg) + { + return (ENXIO); + } + + static int + null_find_next_extcap(device_t dev, device_t child, int capability, int start, int *capreg) + { + return (ENXIO); + } + + static int + null_find_htcap(device_t dev, device_t child, int capability, int *capreg) + { + return (ENXIO); + } + + static int + null_find_next_htcap(device_t dev, device_t child, int capability, int start, int *capreg) + { + return (ENXIO); + } + + static int + null_alloc_msi(device_t dev, device_t child, int *count) + { + return (ENXIO); + } + + static int + null_alloc_msix(device_t dev, device_t child, int *count) + { + return (ENXIO); + } + + static int + null_enable_msi(device_t dev, device_t child, uint64_t address, uint16_t data) + { + return (ENXIO); + } + + static int + null_enable_msix(device_t dev, device_t child, u_int index, uint64_t address, uint16_t data) + { + return (ENXIO); + } + + static void + null_disable_msi(device_t dev, device_t child) + { + } + + static int + null_remap_msix(device_t dev, device_t child, int count, const u_int *vectors) + { + return (ENXIO); + } + + static int + null_release_msi(device_t dev, device_t child) + { + return (ENXIO); + } + + static int + null_get_id(device_t dev, device_t child, enum pci_id_type type, uintptr_t *id) + { + return (ENXIO); + } + + static struct pci_devinfo * + null_alloc_devinfo(device_t dev) + { + return (NULL); + } + + static void + null_child_added(device_t dev, device_t child) + { + } + + static int + null_iov_attach(device_t dev, device_t child, struct nvlist *pf_schema, + struct nvlist *vf_schema, const char *name) + { + return (ENXIO); + } + + static int + null_iov_detach(device_t dev, device_t child) + { + return (ENXIO); + } + }; HEADER { @@ -73,7 +246,7 @@ device_t child; int reg; int width; -}; +} DEFAULT null_read_config; METHOD void write_config { device_t dev; @@ -81,65 +254,65 @@ int reg; u_int32_t val; int width; -}; +} DEFAULT null_write_config; METHOD int get_powerstate { device_t dev; device_t child; -}; +} DEFAULT null_get_powerstate; METHOD int set_powerstate { device_t dev; device_t child; int state; -}; +} DEFAULT null_set_powerstate; METHOD int get_vpd_ident { device_t dev; device_t child; const char **identptr; -}; +} DEFAULT null_get_vpd_ident; METHOD int get_vpd_readonly { device_t dev; device_t child; const char *kw; const char **vptr; -}; +} DEFAULT null_get_vpd_readonly; METHOD int enable_busmaster { device_t dev; device_t child; -}; +} DEFAULT null_enable_busmaster; METHOD int disable_busmaster { device_t dev; device_t child; -}; +} DEFAULT null_disable_busmaster; METHOD int enable_io { device_t dev; device_t child; int space; -}; +} DEFAULT null_enable_io; METHOD int disable_io { device_t dev; device_t child; int space; -}; +} DEFAULT null_disable_io; METHOD int assign_interrupt { device_t dev; device_t child; -}; +} DEFAULT null_assign_interrupt; METHOD int find_cap { device_t dev; device_t child; int capability; int *capreg; -}; +} DEFAULT null_find_cap; METHOD int find_next_cap { device_t dev; @@ -147,14 +320,14 @@ int capability; int start; int *capreg; -}; +} DEFAULT null_find_next_cap; METHOD int find_extcap { device_t dev; device_t child; int capability; int *capreg; -}; +} DEFAULT null_find_extcap; METHOD int find_next_extcap { device_t dev; @@ -162,14 +335,14 @@ int capability; int start; int *capreg; -}; +} DEFAULT null_find_next_extcap; METHOD int find_htcap { device_t dev; device_t child; int capability; int *capreg; -}; +} DEFAULT null_find_htcap; METHOD int find_next_htcap { device_t dev; @@ -177,26 +350,26 @@ int capability; int start; int *capreg; -}; +} DEFAULT null_find_next_htcap; METHOD int alloc_msi { device_t dev; device_t child; int *count; -}; +} DEFAULT null_alloc_msi; METHOD int alloc_msix { device_t dev; device_t child; int *count; -}; +} DEFAULT null_alloc_msix; METHOD void enable_msi { device_t dev; device_t child; uint64_t address; uint16_t data; -}; +} DEFAULT null_enable_msi; METHOD void enable_msix { device_t dev; @@ -204,24 +377,24 @@ u_int index; uint64_t address; uint32_t data; -}; +} DEFAULT null_enable_msix; METHOD void disable_msi { device_t dev; device_t child; -}; +} DEFAULT null_disable_msi; METHOD int remap_msix { device_t dev; device_t child; int count; const u_int *vectors; -}; +} DEFAULT null_remap_msix; METHOD int release_msi { device_t dev; device_t child; -}; +} DEFAULT null_release_msi; METHOD int msi_count { device_t dev; @@ -248,16 +421,16 @@ device_t child; enum pci_id_type type; uintptr_t *id; -}; +} DEFAULT null_get_id; METHOD struct pci_devinfo * alloc_devinfo { device_t dev; -}; +} DEFAULT null_alloc_devinfo; METHOD void child_added { device_t dev; device_t child; -}; +} DEFAULT null_child_added; METHOD int iov_attach { device_t dev; @@ -265,12 +438,12 @@ struct nvlist *pf_schema; struct nvlist *vf_schema; const char *name; -}; +} DEFAULT null_iov_attach; METHOD int iov_detach { device_t dev; device_t child; -}; +} DEFAULT null_iov_detach; METHOD device_t create_iov_child { device_t bus; diff --git a/sys/dev/pci/pci_iov_if.m b/sys/dev/pci/pci_iov_if.m --- a/sys/dev/pci/pci_iov_if.m +++ b/sys/dev/pci/pci_iov_if.m @@ -33,19 +33,38 @@ struct nvlist; } +CODE { + static int + null_init(device_t dev, uint16_t num_vfs, const struct nvlist *config) + { + return (ENXIO); + } + + static void + null_uninit(device_t dev) + { + } + + static int + null_add_vf(device_t dev, uint16_t vfnum, const struct nvlist *config) + { + return (ENXIO); + } +}; + METHOD int init { device_t dev; uint16_t num_vfs; const struct nvlist *config; -}; +} DEFAULT null_init; METHOD void uninit { device_t dev; -}; +} DEFAULT null_uninit; METHOD int add_vf { device_t dev; uint16_t vfnum; const struct nvlist *config; -}; +} DEFAULT null_add_vf; diff --git a/sys/dev/pci/pcib_if.m b/sys/dev/pci/pcib_if.m --- a/sys/dev/pci/pcib_if.m +++ b/sys/dev/pci/pcib_if.m @@ -45,6 +45,70 @@ return (0); } + + static int + null_maxslots(device_t dev) + { + return (ENXIO); + } + + static u_int32_t + null_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) + { + return (ENXIO); + } + + static void + null_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, u_int32_t value, int width) + { + } + + static void + null_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs) + { + } + + static int + null_release_msi(device_t pcib, device_t dev, int count, int *irqs) + { + return (ENXIO); + } + + static int + null_alloc_msix(device_t pcib, device_t dev, int *irq) + { + return (ENXIO); + } + + static int + null_release_msix(device_t pcib, device_t dev, int irq) + { + return (ENXIO); + } + + static int + null_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data) + { + return (ENXIO); + } + + static int + null_power_for_sleep(device_t pcib, device_t dev, int *pstate) + { + return (ENXIO); + } + + static int + null_try_enable_ari(device_t pcib, device_t dev) + { + return (ENXIO); + } + + static int + null_request_feature(device_t pcib, device_t dev, enum pci_feature feature) + { + return (ENXIO); + } }; HEADER { @@ -56,7 +120,7 @@ # METHOD int maxslots { device_t dev; -}; +} DEFAULT null_maxslots; # # @@ -80,7 +144,7 @@ u_int func; u_int reg; int width; -}; +} DEFAULT null_read_config; # # Write configuration space on the PCI bus. The bus, slot and func @@ -97,7 +161,7 @@ u_int reg; u_int32_t value; int width; -}; +} DEFAULT null_write_config; # # Route an interrupt. Returns a value suitable for stuffing into @@ -122,7 +186,7 @@ int count; int maxcount; int *irqs; -}; +} DEFAULT null_alloc_msi; # # Release 'count' MSI messages mapped onto 'count' IRQs stored in the @@ -133,7 +197,7 @@ device_t dev; int count; int *irqs; -}; +} DEFAULT null_release_msi; # # Allocate a single MSI-X message mapped onto '*irq'. @@ -142,7 +206,7 @@ device_t pcib; device_t dev; int *irq; -}; +} DEFAULT null_alloc_msix; # # Release a single MSI-X message mapped onto 'irq'. @@ -151,7 +215,7 @@ device_t pcib; device_t dev; int irq; -}; +} DEFAULT null_release_msix; # # Determine the MSI/MSI-X message address and data for 'irq'. The address @@ -163,7 +227,7 @@ int irq; uint64_t *addr; uint32_t *data; -}; +} DEFAULT null_map_msi; # # Return the device power state to be used during a system sleep state @@ -173,7 +237,7 @@ device_t pcib; device_t dev; int *pstate; -}; +} DEFAULT null_power_for_sleep; # # Return the PCI Routing Identifier (RID) for the device. @@ -192,7 +256,7 @@ METHOD int try_enable_ari { device_t pcib; device_t dev; -}; +} DEFAULT null_try_enable_ari; # # Return non-zero if PCI ARI is enabled, or zero otherwise @@ -219,4 +283,4 @@ device_t pcib; device_t dev; enum pci_feature feature; -}; +} DEFAULT null_request_feature; diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m --- a/sys/kern/bus_if.m +++ b/sys/kern/bus_if.m @@ -83,6 +83,103 @@ { return (NULL); } + + static void + null_probe_nomatch(device_t _dev, device_t _child) + { + return ; + } + + static int + null_read_ivar(device_t _dev, device_t _child, int _indexm, + uintptr_t *_result) + { + return (ENXIO); + } + + static int + null_write_ivar(device_t _dev, device_t _child, int _indx, + uintptr_t _value) + { + return (ENXIO); + } + + static void + null_dev_dev(device_t _dev, device_t _child) + { + return; + } + + static int + null_dev_dev_res(device_t _dev, device_t _child, struct resource *_r) + { + return (ENXIO); + } + + static int + null_adjust_resource(device_t _dev, device_t _child, struct resource *_res, + rman_res_t _start, rman_res_t _end) + { + return (ENXIO); + } + + static int + null_release_resource(device_t _dev, device_t _child, struct resource *_res) + { + return (ENXIO); + } + + static int + null_setup_intr(device_t _dev, device_t _child, struct resource *_irq, int _flags, + driver_filter_t *_filter, driver_intr_t *_intr, void *_arg, + void **_cookiep) + { + return (ENXIO); + } + + static int + null_teardown_intr(device_t _dev, device_t _child, struct resource *_irq, void *_cookie) + { + return (ENXIO); + } + + static int + null_set_resource(device_t _dev, device_t _child, int _type, int _rid, rman_res_t _start, + rman_res_t _count) + { + return (ENXIO); + } + + static int + null_get_resource(device_t _dev, device_t _child, int _type, int _rid, rman_res_t *_startp, + rman_res_t *_countp) + { + return (ENXIO); + } + + static void + null_delete_resource(device_t _dev, device_t _child, int _type, int _rid) + { + return; + } + + static void + null_hinted_child(device_t _dev, const char *_dname, int _dunit) + { + return; + } + + static void + null_hint_device_unit(device_t _dev, device_t _child, const char *_name, int *_unitp) + { + return; + } + + static int + null_reset_child(device_t _dev, device_t _child, int _flags) + { + return (ENXIO); + } }; /** @@ -116,7 +213,7 @@ METHOD void probe_nomatch { device_t _dev; device_t _child; -}; +} DEFAULT null_probe_nomatch; /** * @brief Read the value of a bus-specific attribute of a device @@ -150,7 +247,7 @@ device_t _child; int _index; uintptr_t *_result; -}; +} DEFAULT null_read_ivar; /** * @brief Write the value of a bus-specific attribute of a device @@ -174,7 +271,7 @@ device_t _child; int _indx; uintptr_t _value; -}; +} DEFAULT null_write_ivar; /** * @brief Notify a bus that a child was deleted @@ -188,7 +285,7 @@ METHOD void child_deleted { device_t _dev; device_t _child; -}; +} DEFAULT null_dev_dev; /** * @brief Notify a bus that a child was detached @@ -202,7 +299,7 @@ METHOD void child_detached { device_t _dev; device_t _child; -}; +} DEFAULT null_dev_dev; /** * @brief Notify a bus that a new driver was added @@ -316,7 +413,7 @@ device_t _dev; device_t _child; struct resource *_r; -}; +} DEFAULT null_dev_dev; /** @@ -375,7 +472,7 @@ device_t _dev; device_t _child; struct resource *_r; -}; +} DEFAULT null_dev_dev_res; /** * @brief Adjust a resource @@ -397,7 +494,7 @@ struct resource *_res; rman_res_t _start; rman_res_t _end; -}; +} DEFAULT null_adjust_resource; /** * @brief translate a resource value @@ -433,7 +530,7 @@ device_t _dev; device_t _child; struct resource *_res; -}; +} DEFAULT null_release_resource; /** * @brief Install an interrupt handler @@ -467,7 +564,7 @@ driver_intr_t *_intr; void *_arg; void **_cookiep; -}; +} DEFAULT null_setup_intr; /** * @brief Uninstall an interrupt handler @@ -487,7 +584,7 @@ device_t _child; struct resource *_irq; void *_cookie; -}; +} DEFAULT null_teardown_intr; /** * @brief Suspend an interrupt handler @@ -551,7 +648,7 @@ int _rid; rman_res_t _start; rman_res_t _count; -}; +} DEFAULT null_set_resource; /** * @brief Describe a resource @@ -575,7 +672,7 @@ int _rid; rman_res_t *_startp; rman_res_t *_countp; -}; +} DEFAULT null_get_resource; /** * @brief Delete a resource. @@ -593,7 +690,7 @@ device_t _child; int _type; int _rid; -}; +} DEFAULT null_delete_resource; /** * @brief Return a struct resource_list. @@ -800,7 +897,7 @@ device_t _child; const char *_name; int *_unitp; -}; +} DEFAULT null_hint_device_unit; /** * @brief Notify a bus that the bus pass level has been changed @@ -920,7 +1017,7 @@ device_t _dev; device_t _child; int _flags; -}; +} DEFAULT null_reset_child; /** * @brief Gets child's specific property diff --git a/sys/kern/clock_if.m b/sys/kern/clock_if.m --- a/sys/kern/clock_if.m +++ b/sys/kern/clock_if.m @@ -33,12 +33,24 @@ # An EINVAL error return from this call signifies that the clock has an illegal # setting. + +# +# Default implementation for some code +# + +CODE { + static int + null_dev_ts(device_t dev, struct timespec *ts) { + return ENXIO; + } +}; + METHOD int gettime { device_t dev; struct timespec *ts; -}; +} DEFAULT null_dev_ts; METHOD int settime { device_t dev; struct timespec *ts; -}; +} DEFAULT null_dev_ts; diff --git a/sys/kern/cpufreq_if.m b/sys/kern/cpufreq_if.m --- a/sys/kern/cpufreq_if.m +++ b/sys/kern/cpufreq_if.m @@ -34,6 +34,53 @@ struct cf_setting; }; +# +# Default implementation for some codes +# +CODE { + static int + null_set(device_t dev, const struct cf_level *level, int priority) + { + return ENXIO; + } + + static int + null_get(device_t dev, struct cf_level *level) + { + return ENXIO; + } + + static int + null_level(device_t dev, struct cf_level *levels, int *count) + { + return ENXIO; + } + + static int + null_drv_set(device_t dev, const struct cf_setting *set) + { + return ENXIO; + } + + static int + null_drv_get(device_t dev, const struct cf_setting *set) + { + return ENXIO; + } + + static int + null_drv_settings(device_t dev, struct cf_setting *sets, int *count) + { + return ENXIO; + } + + static int + null_drv_type(device_t dev, int *type) + { + return ENXIO; + } +}; + # cpufreq interface methods # @@ -43,7 +90,7 @@ device_t dev; const struct cf_level *level; int priority; -}; +} DEFAULT null_set; # # Get the current active level. @@ -51,7 +98,7 @@ METHOD int get { device_t dev; struct cf_level *level; -}; +} DEFAULT null_get; # # Get the current possible levels, based on all drivers. @@ -60,7 +107,7 @@ device_t dev; struct cf_level *levels; int *count; -}; +} DEFAULT null_level; # Individual frequency driver methods @@ -70,7 +117,7 @@ METHOD int drv_set { device_t dev; const struct cf_setting *set; -}; +} DEFAULT null_drv_set; # # Get an individual driver's setting. @@ -78,7 +125,7 @@ METHOD int drv_get { device_t dev; struct cf_setting *set; -}; +} DEFAULT null_drv_get; # # Get the settings supported by a driver. @@ -87,7 +134,7 @@ device_t dev; struct cf_setting *sets; int *count; -}; +} DEFAULT null_drv_settings; # # Get an individual driver's type. @@ -95,5 +142,5 @@ METHOD int drv_type { device_t dev; int *type; -}; +} DEFAULT null_drv_type; diff --git a/sys/kern/device_if.m b/sys/kern/device_if.m --- a/sys/kern/device_if.m +++ b/sys/kern/device_if.m @@ -71,6 +71,16 @@ { return NULL; } + + static void null_identify(driver_t *drv, device_t dev) + { + return; + } + + static int null_dev_func(device_t dev) + { + return ENXIO; + } }; /** @@ -154,7 +164,7 @@ } METHOD int probe { device_t dev; -}; +} DEFAULT null_dev_func; /** * @brief Allow a device driver to detect devices not otherwise enumerated. @@ -184,7 +194,7 @@ STATICMETHOD void identify { driver_t *driver; device_t parent; -}; +} DEFAULT null_identify; /** * @brief Attach a device to a device driver @@ -217,7 +227,7 @@ } METHOD int attach { device_t dev; -}; +} DEFAULT null_dev_func; /** * @brief Detach a driver from a device. @@ -243,7 +253,7 @@ */ METHOD int detach { device_t dev; -}; +} DEFAULT null_dev_func; /** * @brief Called during system shutdown. diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -97,6 +97,7 @@ #include #include +#include void mi_startup(void); /* Should be elsewhere */ @@ -255,6 +256,7 @@ */ void mi_startup(void) +__NOCFI { struct sysinit *sip; diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -271,27 +271,44 @@ return (EOPNOTSUPP); } -static int -enxio(void) -{ - return (ENXIO); -} +#define DEFINE_ENXIO_HANDLER(name, ...) \ + static int name(__VA_ARGS__) \ + { \ + return (ENXIO); \ + } -static int -enodev(void) -{ - return (ENODEV); -} +#define DEFINE_ENODEV_HANDLER(name, ...) \ + static int name(__VA_ARGS__) \ + { \ + return (ENODEV); \ + } +#define DEFINE_NULLOP_HANDLER(name, ...) \ + static int \ + name (__VA_ARGS__) \ + { \ + return (0); \ + } + +DEFINE_ENXIO_HANDLER(dead_open_handler, struct cdev *dev, int oflags, int devtype, struct thread *td); +DEFINE_ENXIO_HANDLER(dead_close_handler, struct cdev *dev, int fflag, int devtype, struct thread *td); +DEFINE_ENXIO_HANDLER(dead_read_handler, struct cdev *dev, struct uio *uio, int ioflag); +DEFINE_ENXIO_HANDLER(dead_write_handler, struct cdev *dev, struct uio *uio, int ioflag); +DEFINE_ENXIO_HANDLER(dead_ioctl_handler, struct cdev *dev, u_long cmd, caddr_t data, + int fflag, struct thread *td); +DEFINE_ENODEV_HANDLER(dead_poll_handler, struct cdev *dev, int events, + struct thread *td); +DEFINE_ENODEV_HANDLER(dead_mmap_handler, struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, + int nprot, vm_memattr_t *memattr); /* Define a dead_cdevsw for use when devices leave unexpectedly. */ -#define dead_open (d_open_t *)enxio -#define dead_close (d_close_t *)enxio -#define dead_read (d_read_t *)enxio -#define dead_write (d_write_t *)enxio -#define dead_ioctl (d_ioctl_t *)enxio -#define dead_poll (d_poll_t *)enodev -#define dead_mmap (d_mmap_t *)enodev +#define dead_open dead_open_handler +#define dead_close dead_close_handler +#define dead_read dead_read_handler +#define dead_write dead_write_handler +#define dead_ioctl dead_ioctl_handler +#define dead_poll dead_poll_handler +#define dead_mmap dead_mmap_handler static void dead_strategy(struct bio *bp) @@ -300,8 +317,12 @@ biofinish(bp, NULL, ENXIO); } -#define dead_kqfilter (d_kqfilter_t *)enxio -#define dead_mmap_single (d_mmap_single_t *)enodev +DEFINE_ENXIO_HANDLER(dead_kqfilter_handler, struct cdev *dev, struct knote *kn); +DEFINE_ENODEV_HANDLER(dead_mmap_single_handler, struct cdev *cdev, vm_ooffset_t *offset, + vm_size_t size, struct vm_object **object, int nprot); + +#define dead_kqfilter dead_kqfilter_handler +#define dead_mmap_single dead_mmap_single_handler static struct cdevsw dead_cdevsw = { .d_version = D_VERSION, @@ -320,14 +341,22 @@ /* Default methods if driver does not specify method */ -#define null_open (d_open_t *)nullop -#define null_close (d_close_t *)nullop -#define no_read (d_read_t *)enodev -#define no_write (d_write_t *)enodev -#define no_ioctl (d_ioctl_t *)enodev -#define no_mmap (d_mmap_t *)enodev -#define no_kqfilter (d_kqfilter_t *)enodev -#define no_mmap_single (d_mmap_single_t *)enodev +DEFINE_NULLOP_HANDLER(no_open_handler, struct cdev *dev, int oflags, int devtype, struct thread *td); +DEFINE_NULLOP_HANDLER(no_close_handler, struct cdev *dev, int fflag, int devtype, struct thread *td); +DEFINE_ENODEV_HANDLER(no_read_handler, struct cdev *dev, struct uio *uio, int ioflag); +DEFINE_ENODEV_HANDLER(no_write_handler, struct cdev *dev, struct uio *uio, int ioflag); +DEFINE_ENODEV_HANDLER(no_ioctl_handler, struct cdev *dev, u_long cmd, caddr_t data, + int fflag, struct thread *td); +DEFINE_ENODEV_HANDLER(no_kqfilter_handler, struct cdev *dev, struct knote *kn); + +#define null_open (d_open_t *)no_open_handler +#define null_close (d_close_t *)no_close_handler +#define no_read (d_read_t *)no_read_handler +#define no_write (d_write_t *)no_write_handler +#define no_ioctl (d_ioctl_t *)no_ioctl_handler +#define no_mmap (d_mmap_t *)dead_mmap_handler +#define no_kqfilter (d_kqfilter_t *)no_kqfilter_handler +#define no_mmap_single (d_mmap_single_t *)dead_mmap_single_handler static void no_strategy(struct bio *bp) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -71,6 +71,7 @@ #include #include #include +#include #include #include @@ -1114,7 +1115,7 @@ */ void fork_exit(void (*callout)(void *, struct trapframe *), void *arg, - struct trapframe *frame) + struct trapframe *frame) __NOCFI { struct proc *p; struct thread *td; diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ #include #include #include + #ifdef DDB #include #include @@ -1210,6 +1212,7 @@ static void ithread_execute_handlers(struct proc *p, struct intr_event *ie) +__NOCFI { /* Interrupt handlers should not sleep. */ diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -359,6 +360,7 @@ static void link_elf_invoke_cbs(caddr_t addr, size_t size) +__NOCFI { void (**ctor)(void); size_t i, cnt; @@ -1636,7 +1638,7 @@ static int link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym, - linker_symval_t *symval, bool see_local) + linker_symval_t *symval, bool see_local) __NOCFI { elf_file_t ef; const Elf_Sym *es; @@ -1669,7 +1671,7 @@ static int link_elf_debug_symbol_values(linker_file_t lf, c_linker_sym_t sym, - linker_symval_t *symval) + linker_symval_t *symval) __NOCFI { elf_file_t ef = (elf_file_t)lf; const Elf_Sym *es = (const Elf_Sym *)sym; @@ -1999,7 +2001,7 @@ */ static int elf_lookup_ifunc(linker_file_t lf, Elf_Size symidx, int deps __unused, - Elf_Addr *res) + Elf_Addr *res) __NOCFI { elf_file_t ef; const Elf_Sym *symp; diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -644,6 +645,7 @@ static void link_elf_invoke_cbs(caddr_t addr, size_t size) +__NOCFI { void (**ctor)(void); size_t i, cnt; @@ -1515,7 +1517,7 @@ static int link_elf_symbol_values1(linker_file_t lf, c_linker_sym_t sym, - linker_symval_t *symval, bool see_local) + linker_symval_t *symval, bool see_local) __NOCFI { elf_file_t ef; const Elf_Sym *es; @@ -1690,6 +1692,7 @@ */ static int elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *res) +__NOCFI { elf_file_t ef = (elf_file_t)lf; Elf_Sym *sym; diff --git a/sys/kern/msi_if.m b/sys/kern/msi_if.m --- a/sys/kern/msi_if.m +++ b/sys/kern/msi_if.m @@ -50,6 +50,38 @@ iommu_deinit(device_t dev, device_t child) { } + + static int + null_alloc_msi(device_t dev, device_t child, int count, int maxcount, + device_t *pic, struct intr_irqsrc **srcs) + { + return (ENXIO); + } + + static int + null_release_msi(device_t dev, device_t child, int count, struct intr_irqsrc **srcs) + { + return (ENXIO); + } + + static int + null_alloc_msix(device_t dev, device_t child, device_t *pic, struct intr_irqsrc **src) + { + return (ENXIO); + } + + static int + null_release_msix(device_t dev, device_t child, struct intr_irqsrc *src) + { + return (ENXIO); + } + + static int + null_map_msi(device_t dev, device_t child, struct intr_irqsrc *src, + uint64_t *addr, uint32_t *data) + { + return (ENXIO); + } }; METHOD int alloc_msi { @@ -59,27 +91,27 @@ int maxcount; device_t *pic; struct intr_irqsrc **srcs; -}; +} DEFAULT null_alloc_msi; METHOD int release_msi { device_t dev; device_t child; int count; struct intr_irqsrc **srcs; -}; +} DEFAULT null_release_msi; METHOD int alloc_msix { device_t dev; device_t child; device_t *pic; struct intr_irqsrc **src; -}; +} DEFAULT null_alloc_msix; METHOD int release_msix { device_t dev; device_t child; struct intr_irqsrc *src; -}; +} DEFAULT null_release_msix; METHOD int map_msi { device_t dev; @@ -87,7 +119,7 @@ struct intr_irqsrc *src; uint64_t *addr; uint32_t *data; -}; +} DEFAULT null_map_msi; METHOD int iommu_init { device_t dev; diff --git a/sys/kern/pic_if.m b/sys/kern/pic_if.m --- a/sys/kern/pic_if.m +++ b/sys/kern/pic_if.m @@ -89,6 +89,18 @@ return (EOPNOTSUPP); } + + static void + null_dev_isrc(device_t dev, struct irqsrc *isrc) + { + return; + } + + static int + null_map_intr(device_t dev, struct intr_map_data *data, struct intr_irqsrc **isrcp) + { + return (ENXIO); + } }; METHOD int activate_intr { @@ -106,18 +118,18 @@ METHOD void disable_intr { device_t dev; struct intr_irqsrc *isrc; -}; +} DEFAULT null_dev_isrc; METHOD void enable_intr { device_t dev; struct intr_irqsrc *isrc; -}; +} DEFAULT null_dev_isrc; METHOD int map_intr { device_t dev; struct intr_map_data *data; struct intr_irqsrc **isrcp; -}; +} DEFAULT null_map_intr; METHOD int deactivate_intr { device_t dev; @@ -143,17 +155,17 @@ METHOD void post_filter { device_t dev; struct intr_irqsrc *isrc; -}; +} DEFAULT null_dev_isrc; METHOD void post_ithread { device_t dev; struct intr_irqsrc *isrc; -}; +} DEFAULT null_dev_isrc; METHOD void pre_ithread { device_t dev; struct intr_irqsrc *isrc; -}; +} DEFAULT null_dev_isrc; METHOD void init_secondary { device_t dev; diff --git a/sys/kern/subr_cfi.c b/sys/kern/subr_cfi.c new file mode 100644 --- /dev/null +++ b/sys/kern/subr_cfi.c @@ -0,0 +1,58 @@ +#include + +#include "opt_printf.h" + +#ifdef _KERNEL +#include +#include +#include +#include +#include +#endif + +#ifdef _KERNEL +#include +#include +#endif + +FEATURE(kcfi, "Kernel control flow integration"); + +static SYSCTL_NODE(_debug, OID_AUTO, kcfi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, + "KCFI options"); + +static bool cfi_panic __read_mostly = false; +SYSCTL_BOOL(_debug_kcfi, OID_AUTO, panic_on_violation, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, + &cfi_panic, 0, "KCFI panic on violation is disabled"); + +static bool cfi_disabled __read_mostly = false; +SYSCTL_BOOL(_debug_kcfi, OID_AUTO, disabled, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, + &cfi_disabled, 0, "Disable KCFI message"); + +#ifdef _KERNEL +static void +report_cfi(struct trapframe *frame, register_t func_addr, uint32_t type) { + static char *cfi_format_str = "CFI chcek failed on ip %lx for callee %lx and type %x\n"; + register_t addr = TRAPF_PC(frame); + + if (cfi_panic) + panic(cfi_format_str, addr, func_addr, type); + else + printf(cfi_format_str, addr, func_addr, type); +} +#endif + +#ifdef _KERNEL +bool +cfi_handler(struct trapframe *frame) { + register_t func_addr; + uint32_t type; + + if (decode_cfi(frame, &func_addr, &type)) { + report_cfi(frame, func_addr, type); + TRAPF_PC(frame) += 2; + return (true); + } + + return (false); +} +#endif diff --git a/sys/kern/subr_epoch.c b/sys/kern/subr_epoch.c --- a/sys/kern/subr_epoch.c +++ b/sys/kern/subr_epoch.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef EPOCH_TRACE #include #include @@ -802,6 +803,7 @@ static void epoch_call_task(void *arg __unused) +__NOCFI { ck_stack_entry_t *cursor, *head, *next; ck_epoch_record_t *record; diff --git a/sys/kern/subr_scanf.c b/sys/kern/subr_scanf.c --- a/sys/kern/subr_scanf.c +++ b/sys/kern/subr_scanf.c @@ -39,6 +39,7 @@ #include #include #include +#include /* * Note that stdarg.h and the ANSI style va_start macro is used for both @@ -101,6 +102,7 @@ int vsscanf(const char *inp, char const *fmt0, va_list ap) +__NOCFI { int inr; const u_char *fmt = (const u_char *)fmt0; diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef KTRACE #include #include @@ -50,7 +51,7 @@ #include static inline void -syscallenter(struct thread *td) +syscallenter(struct thread *td) __NOCFI { struct proc *p; struct syscall_args *sa; diff --git a/sys/net/vnet.c b/sys/net/vnet.c --- a/sys/net/vnet.c +++ b/sys/net/vnet.c @@ -53,6 +53,7 @@ #include #include #include +#include #include @@ -512,6 +513,7 @@ */ void vnet_register_sysinit(void *arg) +__NOCFI { struct vnet_sysinit *vs, *vs2; struct vnet *vnet; diff --git a/sys/sys/cfi.h b/sys/sys/cfi.h new file mode 100644 --- /dev/null +++ b/sys/sys/cfi.h @@ -0,0 +1,22 @@ +/* + */ +#ifndef _SYS_CFI_H_ +#define _SYS_CFI_H_ + +#ifdef _KERNEL + +#include +#include + +#ifdef KCFI +#define __NOCFI __attribute__((__no_sanitize__("kcfi"))) +#else +#define __NOCFI +#endif + +bool +cfi_handler(struct trapframe *); + +#endif /* _KERNEL */ + +#endif /* _SYS_CFI_H_ */