From a4cae615b81bd6691e1856c18f4058a9f7f06178 Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Mon, 18 Jan 2016 05:28:30 -0500 Subject: [PATCH] dtrace: correct probe disable behaviour for syscalls Previously, when both entry and return probes were enabled for a syscall, upon disabling one of them, the function pointer in the syscall table would already be reset to the default, removing the interceptor. This resulted in an inconsistent state when the 2nd probe would get removed, and could cause a nasty race if one were to try to enable one of the probes in between. We now only remove the interceptor when we know the last probe is being disabled. Orabug: 22352636 Signed-off-by: Kris Van Hees Acked-by: Nick Alcock --- dtrace/systrace_dev.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dtrace/systrace_dev.c b/dtrace/systrace_dev.c index 8727637a4b73..49ebb4040ce8 100644 --- a/dtrace/systrace_dev.c +++ b/dtrace/systrace_dev.c @@ -131,11 +131,16 @@ void _systrace_disable(void *arg, dtrace_id_t id, void *parg) { int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg); dtrace_syscalls_t *sc = &systrace_info->sysent[sysnum]; - int enabled = sc->stsy_entry != DTRACE_IDNONE || - sc->stsy_return != DTRACE_IDNONE; + int enabled = + (sc->stsy_entry != DTRACE_IDNONE ? 1 : 0) + + (sc->stsy_return != DTRACE_IDNONE ? 1 : 0); dt_sys_call_t intercept = get_intercept(sysnum); - if (enabled) + /* + * Every syscall can have 2 probes associated with it. We need to keep + * the interceptor in place until the last probe is getting disabled. + */ + if (enabled == 1) (void)cmpxchg((uint32_t *)sc->stsy_tblent, (uint32_t)intercept, (uint32_t)sc->stsy_underlying); -- 2.50.1