Page MenuHomeFreeBSD

D46193.id141591.diff
No OneTemporary

D46193.id141591.diff

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 <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/cfi.h>
+#include <machine/frame.h>
+
+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 <sys/param.h>
#include <sys/asan.h>
#include <sys/bus.h>
+#include <sys/cfi.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
@@ -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 <sys/types.h>
+
+
+#include <machine/proc.h>
+#include <machine/reg.h>
+
+
+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 <sys/linker.h>
+#include <sys/cfi.h>
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 <ddb/ddb.h>
#include <ddb/db_sym.h>
+#include <sys/cfi.h>
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 <sys/sx.h>
#include <sys/sysent.h>
#include <sys/signalvar.h>
+#include <sys/cfi.h>
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -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 <sys/random.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
+#include <sys/cfi.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
@@ -61,6 +62,7 @@
#include <machine/md_var.h>
#include <machine/smp.h>
#include <machine/stdarg.h>
+
#ifdef DDB
#include <ddb/ddb.h>
#include <ddb/db_sym.h>
@@ -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 <sys/linker.h>
#include <sys/sysctl.h>
#include <sys/tslog.h>
+#include <sys/cfi.h>
#include <machine/elf.h>
@@ -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 <sys/rwlock.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
+#include <sys/cfi.h>
#include <machine/elf.h>
@@ -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 <sys/cdefs.h>
+
+#include "opt_printf.h"
+
+#ifdef _KERNEL
+#include <sys/priv.h>
+#include <sys/cfi.h>
+#include <sys/systm.h>
+#include <sys/kassert.h>
+#include <sys/sysctl.h>
+#endif
+
+#ifdef _KERNEL
+#include <machine/cpu.h>
+#include <machine/cfi.h>
+#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 <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/turnstile.h>
+#include <sys/cfi.h>
#ifdef EPOCH_TRACE
#include <machine/stdarg.h>
#include <sys/stack.h>
@@ -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 <sys/ctype.h>
#include <sys/limits.h>
#include <sys/stddef.h>
+#include <sys/cfi.h>
/*
* 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 <sys/capsicum.h>
#include <sys/ktr.h>
#include <sys/vmmeter.h>
+#include <sys/cfi.h>
#ifdef KTRACE
#include <sys/uio.h>
#include <sys/ktrace.h>
@@ -50,7 +51,7 @@
#include <security/audit/audit.h>
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 <sys/socket.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
+#include <sys/cfi.h>
#include <machine/stdarg.h>
@@ -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 <sys/types.h>
+#include <sys/proc.h>
+
+#ifdef KCFI
+#define __NOCFI __attribute__((__no_sanitize__("kcfi")))
+#else
+#define __NOCFI
+#endif
+
+bool
+cfi_handler(struct trapframe *);
+
+#endif /* _KERNEL */
+
+#endif /* _SYS_CFI_H_ */

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 23, 8:21 PM (4 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24067789
Default Alt Text
D46193.id141591.diff (46 KB)

Event Timeline