* Use is subject to license terms.
*/
-/* #pragma ident "@(#)systrace.c 1.6 06/09/19 SMI" */
-
-#ifdef KERNEL
-#ifndef _KERNEL
-#define _KERNEL /* Solaris vs. Darwin */
-#endif
-#endif
+#include <ptrauth.h>
#include <kern/thread.h>
#include <mach/thread_status.h>
#define LOADABLE_SYSCALL(a) 0 /* Not pertinent to Darwin. */
#define LOADED_SYSCALL(a) 1 /* Not pertinent to Darwin. */
-extern lck_attr_t* dtrace_lck_attr;
-extern lck_grp_t* dtrace_lck_grp;
-static lck_mtx_t dtrace_systrace_lock; /* probe state lock */
+static LCK_MTX_DECLARE_ATTR(dtrace_systrace_lock,
+ &dtrace_lck_grp, &dtrace_lck_attr); /* probe state lock */
systrace_sysent_t *systrace_sysent = NULL;
void (*systrace_probe)(dtrace_id_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
#define systrace_init _systrace_init
static void
-systrace_init(struct sysent *actual, systrace_sysent_t **interposed)
+systrace_init(const struct sysent *actual, systrace_sysent_t **interposed)
{
systrace_sysent_t *ssysent = *interposed; /* Avoid sysent shadow warning
* from bsd/sys/sysent.h */
}
for (i = 0; i < NSYSCALL; i++) {
- struct sysent *a = &actual[i];
+ const struct sysent *a = &actual[i];
systrace_sysent_t *s = &ssysent[i];
if (LOADABLE_SYSCALL(a) && !LOADED_SYSCALL(a)) {
s->stsy_underlying = a->sy_callc;
s->stsy_return_type = a->sy_return_type;
}
- lck_mtx_init(&dtrace_systrace_lock, dtrace_lck_grp, dtrace_lck_attr);
}
lck_mtx_lock(&dtrace_systrace_lock);
if (sysent[sysnum].sy_callc == systrace_sysent[sysnum].stsy_underlying) {
- vm_offset_t dss = (vm_offset_t)&dtrace_systrace_syscall;
+ /* It is not possible to write to sysent[] directly because it is const. */
+ vm_offset_t dss = ptrauth_nop_cast(vm_offset_t, &dtrace_systrace_syscall);
ml_nofault_copy((vm_offset_t)&dss, (vm_offset_t)&sysent[sysnum].sy_callc, sizeof(vm_offset_t));
}
lck_mtx_unlock(&dtrace_systrace_lock);
+
return 0;
}
systrace_sysent[sysnum].stsy_return == DTRACE_IDNONE);
if (disable) {
+ /*
+ * Usage of volatile protects the if statement below from being optimized away.
+ *
+ * Compilers are clever and know that const array values can't change in time
+ * and the if below is always false. That is because it can't see that DTrace
+ * injects dtrace_systrace_syscall dynamically and violates constness of the
+ * array.
+ */
+ volatile const struct sysent *syscallent = &sysent[sysnum];
+
lck_mtx_lock(&dtrace_systrace_lock);
- if (sysent[sysnum].sy_callc == dtrace_systrace_syscall) {
- ml_nofault_copy((vm_offset_t)&systrace_sysent[sysnum].stsy_underlying, (vm_offset_t)&sysent[sysnum].sy_callc, sizeof(systrace_sysent[sysnum].stsy_underlying));
+ if (syscallent->sy_callc == dtrace_systrace_syscall) {
+ ml_nofault_copy((vm_offset_t)&systrace_sysent[sysnum].stsy_underlying,
+ (vm_offset_t)&syscallent->sy_callc, sizeof(vm_offset_t));
}
lck_mtx_unlock(&dtrace_systrace_lock);
}
#endif /* MACH_ASSERT */
} mach_trap_t;
-extern const mach_trap_t mach_trap_table[]; /* syscall_sw.h now declares this as const */
-extern int mach_trap_count;
+extern const mach_trap_t mach_trap_table[]; /* syscall_sw.h now declares this as const */
+extern const int mach_trap_count;
-extern const char *mach_syscall_name_table[];
+extern const char *const mach_syscall_name_table[];
/* XXX From osfmk/i386/bsd_i386.c */
struct mach_call_args {
lck_mtx_lock(&dtrace_systrace_lock);
if (mach_trap_table[sysnum].mach_trap_function == machtrace_sysent[sysnum].stsy_underlying) {
- vm_offset_t dss = (vm_offset_t)&dtrace_machtrace_syscall;
+ /* It is not possible to write to mach_trap_table[] directly because it is const. */
+ vm_offset_t dss = ptrauth_nop_cast(vm_offset_t, &dtrace_machtrace_syscall);
ml_nofault_copy((vm_offset_t)&dss, (vm_offset_t)&mach_trap_table[sysnum].mach_trap_function, sizeof(vm_offset_t));
}
machtrace_sysent[sysnum].stsy_return == DTRACE_IDNONE);
if (disable) {
- lck_mtx_lock(&dtrace_systrace_lock);
+ /*
+ * Usage of volatile protects the if statement below from being optimized away.
+ *
+ * Compilers are clever and know that const array values can't change in time
+ * and the if below is always false. That is because it can't see that DTrace
+ * injects dtrace_machtrace_syscall dynamically and violates constness of the
+ * array.
+ */
+ volatile const mach_trap_t *machtrap = &mach_trap_table[sysnum];
- if (mach_trap_table[sysnum].mach_trap_function == (mach_call_t)dtrace_machtrace_syscall) {
- ml_nofault_copy((vm_offset_t)&machtrace_sysent[sysnum].stsy_underlying, (vm_offset_t)&mach_trap_table[sysnum].mach_trap_function, sizeof(vm_offset_t));
+ lck_mtx_lock(&dtrace_systrace_lock);
+ if (machtrap->mach_trap_function == (mach_call_t)dtrace_machtrace_syscall) {
+ ml_nofault_copy((vm_offset_t)&machtrace_sysent[sysnum].stsy_underlying,
+ (vm_offset_t)&machtrap->mach_trap_function, sizeof(vm_offset_t));
}
lck_mtx_unlock(&dtrace_systrace_lock);
}
#define SYSTRACE_MAJOR -24 /* let the kernel pick the device number */
-/*
- * A struct describing which functions will get invoked for certain
- * actions.
- */
static struct cdevsw systrace_cdevsw =
{
- _systrace_open, /* open */
- eno_opcl, /* close */
- eno_rdwrt, /* read */
- eno_rdwrt, /* write */
- eno_ioctl, /* ioctl */
- (stop_fcn_t *)nulldev, /* stop */
- (reset_fcn_t *)nulldev, /* reset */
- NULL, /* tty's */
- eno_select, /* select */
- eno_mmap, /* mmap */
- eno_strat, /* strategy */
- eno_getc, /* getc */
- eno_putc, /* putc */
- 0 /* type */
+ .d_open = _systrace_open,
+ .d_close = eno_opcl,
+ .d_read = eno_rdwrt,
+ .d_write = eno_rdwrt,
+ .d_ioctl = eno_ioctl,
+ .d_stop = (stop_fcn_t *)nulldev,
+ .d_reset = (reset_fcn_t *)nulldev,
+ .d_select = eno_select,
+ .d_mmap = eno_mmap,
+ .d_strategy = eno_strat,
+ .d_reserved_1 = eno_getc,
+ .d_reserved_2 = eno_putc,
};
void systrace_init( void );