Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133085071
D46193.id141591.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
46 KB
Referenced Files
None
Subscribers
None
D46193.id141591.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D46193: sys: implement Kernel CFI from clang
Attached
Detach File
Event Timeline
Log In to Comment