]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/dtrace/systrace.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / dev / dtrace / systrace.c
index 27d199eebc7b98d375769ae0d3a2ee683b6edea3..1342e7785875b4d3a1cf25f8662cfc431bda6ba9 100644 (file)
  * 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>
@@ -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 );