]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: syscall entry/return probes.
authorKris Van Hees <kris.van.hees@oracle.com>
Wed, 31 Aug 2011 03:28:03 +0000 (23:28 -0400)
committerNick Alcock <nick.alcock@oracle.com>
Mon, 29 Jun 2015 21:39:54 +0000 (22:39 +0100)
Makes the sys call table writable, and replaces the function pointer
for select syscalls with the address of a wrapper function to enable
entry and return probe firing.

Fix for address range checking for copyin(str) operations and relatives.
It was using an incorrect boundary address, causing problems for some cases.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
arch/x86/include/asm/syscall.h
arch/x86/kernel/syscall_64.c
kernel/dtrace/dtrace_os.c

index d6a756ae04c8b999ed379159aa03029b17a38139..41e85edc33480d7dd949757e007bff17d42738f0 100644 (file)
 #include <asm/unistd.h>
 
 typedef void (*sys_call_ptr_t)(void);
+#if defined(CONFIG_DT_SYSTRACE) || defined(CONFIG_DT_SYSTRACE_MODULE)
+extern sys_call_ptr_t sys_call_table[];
+#else
 extern const sys_call_ptr_t sys_call_table[];
+#endif
 
 /*
  * Only the low 32 bits of orig_ax are meaningful, so we return int.
index 4ac730b37f0bf4de7ef67fd7f869d9f756e207ed..2593443ee3e5ebc5182d31bfd5ce2b9501458c89 100644 (file)
 
 extern void sys_ni_syscall(void);
 
+#if defined(CONFIG_DT_SYSTRACE) || defined(CONFIG_DT_SYSTRACE_MODULE)
+asmlinkage sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
+#else
 asmlinkage const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = {
+#endif /* CONFIG_DT_SYSTRACE || CONFIG_DT_SYSTRACE_MODULE */
        /*
         * Smells like a compiler bug -- it doesn't work
         * when the & below is removed.
index 07d5a8a5a4c99bb428093640e54af7d1aa0ac0f9..fdb36a9deb1c875c709ef113de57b4eab7dbb8fb 100644 (file)
@@ -8,8 +8,10 @@
 #include <linux/hrtimer.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#include <asm/unistd.h>
 
 #include "cyclic.h"
+#include "systrace.h"
 
 /*
  * Very basic implementation of cyclics, merely enough to support dtrace.
@@ -132,3 +134,62 @@ void cyclic_remove(cyclic_id_t id)
        mutex_unlock(&cyclic_lock);
 }
 EXPORT_SYMBOL(cyclic_remove);
+
+static systrace_info_t systrace_info;
+
+void (*systrace_probe)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
+                      uintptr_t, uintptr_t);
+
+void systrace_stub(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
+                  uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
+                  uintptr_t arg5)
+{
+}
+
+asmlinkage long systrace_syscall(uintptr_t arg0, uintptr_t arg1,
+                                uintptr_t arg2, uintptr_t arg3,
+                                uintptr_t arg4, uintptr_t arg5)
+{
+       long                    rc;
+       unsigned long           sysnum;
+       dtrace_id_t             id;
+       dtrace_syscalls_t       *sc;
+
+       asm volatile("movq %%rax,%0" : "=m"(sysnum));
+
+       sc = &systrace_info.sysent[sysnum];
+
+       if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+               (*systrace_probe)(id, arg0, arg1, arg2, arg3, arg4, arg5);
+
+       /*
+        * FIXME: Add stop functionality for DTrace.
+        */
+
+       if (sc->stsy_underlying != NULL)
+               rc = (*sc->stsy_underlying)(arg0, arg1, arg2, arg3, arg4,
+                                           arg5);
+
+       if ((id = sc->stsy_return) != DTRACE_IDNONE)
+               (*systrace_probe)(id, arg0, arg1, arg2, arg3, arg4, arg5);
+
+       return rc;
+}
+
+systrace_info_t *dtrace_syscalls_init() {
+       int                     i;
+       extern sys_call_ptr_t   sys_call_table[NR_syscalls];
+
+       systrace_info.probep = &systrace_probe;
+       systrace_info.stub = systrace_stub;
+       systrace_info.syscall = systrace_syscall;
+
+       for (i = 0; i < NR_syscalls; i++) {
+               systrace_info.sysent[i].stsy_tblent = &sys_call_table[i];
+               systrace_info.sysent[i].stsy_underlying =
+                                       (dt_sys_call_t)sys_call_table[i];
+       }
+
+       return &systrace_info;
+}
+EXPORT_SYMBOL(dtrace_syscalls_init);