X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0a7de7458d150b5d4dffc935ba399be265ef0a1a..HEAD:/bsd/dev/dtrace/systrace.c diff --git a/bsd/dev/dtrace/systrace.c b/bsd/dev/dtrace/systrace.c index 27d199eeb..1342e7785 100644 --- a/bsd/dev/dtrace/systrace.c +++ b/bsd/dev/dtrace/systrace.c @@ -23,13 +23,7 @@ * 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 #include #include @@ -88,9 +82,8 @@ extern const char *syscallnames[]; #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); @@ -386,7 +379,7 @@ static dtrace_provider_id_t systrace_id; #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 */ @@ -398,7 +391,7 @@ systrace_init(struct sysent *actual, systrace_sysent_t **interposed) } 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)) { @@ -412,7 +405,6 @@ systrace_init(struct sysent *actual, systrace_sysent_t **interposed) 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); } @@ -495,10 +487,12 @@ systrace_enable(void *arg, dtrace_id_t id, void *parg) 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; } @@ -513,9 +507,20 @@ systrace_disable(void *arg, dtrace_id_t id, void *parg) 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); } @@ -611,10 +616,10 @@ typedef struct { #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 { @@ -851,7 +856,8 @@ machtrace_enable(void *arg, dtrace_id_t id, void *parg) 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)); } @@ -871,10 +877,20 @@ machtrace_disable(void *arg, dtrace_id_t id, void *parg) 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); } @@ -936,26 +952,20 @@ _systrace_open(dev_t dev, int flags, int devtype, struct proc *p) #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 );