From patchwork Wed Jun 30 15:47:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 12352493 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5EA15C11F6E for ; Wed, 30 Jun 2021 15:47:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 43C8F61477 for ; Wed, 30 Jun 2021 15:47:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235892AbhF3PuC (ORCPT ); Wed, 30 Jun 2021 11:50:02 -0400 Received: from mail.kernel.org ([198.145.29.99]:59424 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235893AbhF3PuA (ORCPT ); Wed, 30 Jun 2021 11:50:00 -0400 Received: from gandalf.local.home (cpe-66-24-58-225.stny.res.rr.com [66.24.58.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 3040861493; Wed, 30 Jun 2021 15:47:31 +0000 (UTC) Received: from rostedt by gandalf.local.home with local (Exim 4.94.2) (envelope-from ) id 1lycR0-000XoV-0b; Wed, 30 Jun 2021 11:47:30 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (VMware)" Subject: [PATCH v2 1/4] libtracefs: Implement tracefs_instances() Date: Wed, 30 Jun 2021 11:47:26 -0400 Message-Id: <20210630154729.129873-2-rostedt@goodmis.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210630154729.129873-1-rostedt@goodmis.org> References: <20210630154729.129873-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" Implement tracefs_instances() that will take a regex (or NULL for all) and return a list of instances in the system. Signed-off-by: Steven Rostedt (VMware) --- include/tracefs.h | 1 + src/tracefs-instance.c | 78 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/include/tracefs.h b/include/tracefs.h index da8ad4189d4d..a21d2d2f22a6 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -44,6 +44,7 @@ int tracefs_instance_file_read_number(struct tracefs_instance *instance, int tracefs_instance_file_open(struct tracefs_instance *instance, const char *file, int mode); int tracefs_instances_walk(int (*callback)(const char *, void *), void *context); +char **tracefs_instances(const char *regex); bool tracefs_instance_exists(const char *name); bool tracefs_file_exists(struct tracefs_instance *instance, const char *name); diff --git a/src/tracefs-instance.c b/src/tracefs-instance.c index 2aeb529903bd..d833fae0fb0c 100644 --- a/src/tracefs-instance.c +++ b/src/tracefs-instance.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include "tracefs.h" @@ -630,6 +631,83 @@ out: return fret; } +static inline bool match(const char *str, regex_t *re) +{ + if (!re) + return true; + return regexec(re, str, 0, NULL, 0) == 0; +} + +struct instance_list { + regex_t *re; + char **list; + int size; + int failed; +}; + +static int build_list(const char *name, void *data) +{ + struct instance_list *list = data; + char **instances; + int ret = -1; + + if (!match(name, list->re)) + return 0; + + instances = realloc(list->list, list->size + 2); + if (!instances) + goto out; + + list->list = instances; + list->list[list->size] = strdup(name); + if (!list->list[list->size]) + goto out; + + list->size++; + ret = 0; + + out: + list->failed = ret; + return ret; +} + +/** + * tracefs_instances - return a list of instance names + * @regex: A regex of instances to filter on (NULL to match all) + * + * Returns a list of names of existing instances, that must be + * freed with tracefs_list_free(). Note, if there are no matches + * then an empty list will be returned (not NULL). + * NULL on error. + */ +char **tracefs_instances(const char *regex) +{ + struct instance_list list = { .re = NULL, .list = NULL }; + regex_t re; + int ret; + + if (regex) { + ret = regcomp(&re, regex, REG_ICASE|REG_NOSUB); + if (ret < 0) + return NULL; + list.re = &re; + } + + ret = tracefs_instances_walk(build_list, &list); + if (ret < 0 || list.failed) { + tracefs_list_free(list.list); + list.list = NULL; + } else { + if (!list.list) { + /* No matches should produce an empty list */ + list.list = malloc(sizeof(*list.list)); + if (list.list) + list.list[0] = NULL; + } + } + return list.list; +} + /** * tracefs_get_clock - Get the current trace clock * @instance: ftrace instance, can be NULL for the top instance From patchwork Wed Jun 30 15:47:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 12352489 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 44C30C11F6A for ; Wed, 30 Jun 2021 15:47:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 341F861492 for ; Wed, 30 Jun 2021 15:47:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235871AbhF3PuB (ORCPT ); Wed, 30 Jun 2021 11:50:01 -0400 Received: from mail.kernel.org ([198.145.29.99]:59416 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235884AbhF3PuA (ORCPT ); Wed, 30 Jun 2021 11:50:00 -0400 Received: from gandalf.local.home (cpe-66-24-58-225.stny.res.rr.com [66.24.58.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2775E6147D; Wed, 30 Jun 2021 15:47:31 +0000 (UTC) Received: from rostedt by gandalf.local.home with local (Exim 4.94.2) (envelope-from ) id 1lycR0-000XoX-1N; Wed, 30 Jun 2021 11:47:30 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (VMware)" Subject: [PATCH v2 2/4] libtracefs: Implement tracefs_kprobe_raw() Date: Wed, 30 Jun 2021 11:47:27 -0400 Message-Id: <20210630154729.129873-3-rostedt@goodmis.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210630154729.129873-1-rostedt@goodmis.org> References: <20210630154729.129873-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" Add a function to facilitate creating a kprobe event. It has the "raw" in its name because it still requires knowing the format of the kprobe. But does handle the kprobe naming better and writing to the kprobe_event file. Signed-off-by: Steven Rostedt (VMware) --- include/tracefs.h | 4 +++ src/Makefile | 1 + src/tracefs-kprobes.c | 70 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/tracefs-kprobes.c diff --git a/include/tracefs.h b/include/tracefs.h index a21d2d2f22a6..bc504bcb0188 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -214,4 +214,8 @@ int tracefs_tracer_clear(struct tracefs_instance *instance); ssize_t tracefs_trace_pipe_stream(int fd, struct tracefs_instance *instance, int flags); ssize_t tracefs_trace_pipe_print(struct tracefs_instance *instance, int flags); void tracefs_trace_pipe_stop(struct tracefs_instance *instance); + +int tracefs_kprobe_raw(const char *system, const char *event, + const char *addr, const char *format); + #endif /* _TRACE_FS_H */ diff --git a/src/Makefile b/src/Makefile index b4cff07efc50..0697a047f4bc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,6 +8,7 @@ OBJS += tracefs-instance.o OBJS += tracefs-events.o OBJS += tracefs-tools.o OBJS += tracefs-marker.o +OBJS += tracefs-kprobes.o OBJS := $(OBJS:%.o=$(bdir)/%.o) DEPS := $(OBJS:$(bdir)/%.o=$(bdir)/.%.d) diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c new file mode 100644 index 000000000000..e4b28cff9f08 --- /dev/null +++ b/src/tracefs-kprobes.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2021 VMware Inc, Steven Rostedt + * + * Updates: + * Copyright (C) 2021, VMware, Tzvetomir Stoyanov + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tracefs.h" +#include "tracefs-local.h" + +#define KPROBE_EVENTS "kprobe_events" + +/** + * tracefs_kprobe_raw - Create a kprobe using raw format + * @system: The system name (NULL for the default kprobes) + * @event: The event to create (NULL to use @addr for the event) + * @addr: The function and offset (or address) to insert the probe + * @format: The raw format string to define the probe. + * + * Create a kprobe that will be in the @system group (or kprobes if + * @system is NULL). Have the name of @event (or @addr if @event is + * NULL). Will be inserted to @addr (function name, with or without + * offset, or a address). And the @format will define the raw format + * of the kprobe. See the Linux documentation file under: + * Documentation/trace/kprobetrace.rst + * + * Return 0 on success, or -1 on error. + * If the syntex of @format was incorrect, running + * tracefs_error_last(NULL) may show what went wrong. + * + * errno will be set to EBADMSG if addr or format is NULL. + */ +int tracefs_kprobe_raw(const char *system, const char *event, + const char *addr, const char *format) +{ + char *str; + int ret; + + errno = EBADMSG; + if (!addr || !format) + return -1; + + if (!event) + event = addr; + + if (system) + ret = asprintf(&str, "p:%s/%s %s %s\n", + system, event, addr, format); + else + ret = asprintf(&str, "p:%s %s %s\n", + event, addr, format); + + if (ret < 0) + return -1; + + ret = tracefs_instance_file_append(NULL, KPROBE_EVENTS, str); + free(str); + + return ret < 0 ? ret : 0; +} From patchwork Wed Jun 30 15:47:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 12352487 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46E2EC11F6B for ; Wed, 30 Jun 2021 15:47:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2364861483 for ; Wed, 30 Jun 2021 15:47:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235914AbhF3PuA (ORCPT ); Wed, 30 Jun 2021 11:50:00 -0400 Received: from mail.kernel.org ([198.145.29.99]:59418 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235871AbhF3PuA (ORCPT ); Wed, 30 Jun 2021 11:50:00 -0400 Received: from gandalf.local.home (cpe-66-24-58-225.stny.res.rr.com [66.24.58.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2967961474; Wed, 30 Jun 2021 15:47:31 +0000 (UTC) Received: from rostedt by gandalf.local.home with local (Exim 4.94.2) (envelope-from ) id 1lycR0-000XoZ-2I; Wed, 30 Jun 2021 11:47:30 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (VMware)" Subject: [PATCH v2 3/4] libtracefs: Implement tracefs_kprobe_clear() to remove all kprobes Date: Wed, 30 Jun 2021 11:47:28 -0400 Message-Id: <20210630154729.129873-4-rostedt@goodmis.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210630154729.129873-1-rostedt@goodmis.org> References: <20210630154729.129873-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" A call to tracefs_kprobe_clear() will attempt to disable all kprobes. If any kprobe is set, and the @force parameter is set, it will fail with errno set to EBUSY. If @force is set, then it will attempt to disable all the defined kprobe events and then clear it. Signed-off-by: Steven Rostedt (VMware) --- include/tracefs.h | 2 +- src/tracefs-kprobes.c | 116 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/include/tracefs.h b/include/tracefs.h index bc504bcb0188..19b9b49d2dae 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -217,5 +217,5 @@ void tracefs_trace_pipe_stop(struct tracefs_instance *instance); int tracefs_kprobe_raw(const char *system, const char *event, const char *addr, const char *format); - +int tracefs_kprobe_clear(bool force); #endif /* _TRACE_FS_H */ diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c index e4b28cff9f08..a6faf69fc010 100644 --- a/src/tracefs-kprobes.c +++ b/src/tracefs-kprobes.c @@ -68,3 +68,119 @@ int tracefs_kprobe_raw(const char *system, const char *event, return ret < 0 ? ret : 0; } + +struct instance_list { + struct instance_list *next; + struct tracefs_instance *instance; +}; + +static void disable_events(const char *system, const char *event, + char **list) +{ + struct tracefs_instance *instance; + int i; + + /* + * Note, this will not fail even on error. + * That is because even if something fails, it may still + * work enough to clear the kprobes. If that's the case + * the clearing after the loop will succeed and the function + * is a success, even though other parts had failed. If + * one of the kprobe events is enabled in one of the + * instances that fail, then the clearing will fail too + * and the function will return an error. + */ + + tracefs_event_disable(NULL, system, event); + /* No need to test results */ + + if (!list) + return; + + for (i = 0; list[i]; i++) { + instance = tracefs_instance_alloc(NULL, list[i]); + /* If this fails, try the next one */ + if (!instance) + continue; + tracefs_event_disable(instance, system, event); + tracefs_instance_free(instance); + } + return; +} + +/** + * tracefs_kprobe_clear - clear kprobe events + * @force: Will attempt to disable all kprobe events and clear them + * + * Will remove all defined kprobe events. If any of them are enabled, + * and @force is not set, then it will error with -1 and errno to be + * EBUSY. If @force is set, then it will attempt to disable all the kprobe + * events in all instances, and try again. + * + * Returns zero on success, -1 otherwise. + */ +int tracefs_kprobe_clear(bool force) +{ + char **instance_list; + char *content; + char *saveptr; + char *system; + char *event; + char *p; + int ret; + + ret = tracefs_instance_file_clear(NULL, KPROBE_EVENTS); + if (!ret) + return 0; + + if (!force) + return -1; + + /* Attempt to disable all kprobe events */ + content = tracefs_instance_file_read(NULL, KPROBE_EVENTS, NULL); + if (!content) + return -1; + + instance_list = tracefs_instances(NULL); + /* + * Even if the above failed and instance_list is NULL, + * keep going, as the enabled event may simply be in the + * top level. + */ + + ret = -1; + p = strtok_r(content, ":", &saveptr); + if (!p) + goto out; + + for (;;) { + p = strtok_r(NULL, "/", &saveptr); + if (!p) + goto out; + + system = p; + + p = strtok_r(NULL," ", &saveptr); + if (!p) + goto out; + event = p; + + disable_events(system, event, instance_list); + + ret = tracefs_instance_file_clear(NULL, KPROBE_EVENTS); + /* On success stop the loop */ + if (!ret) + goto out; + + ret = -1; + p = strtok_r(NULL, "\n", &saveptr); + if (!p) + goto out; + + p = strtok_r(NULL, ":", &saveptr); + } + out: + tracefs_list_free(instance_list); + free(content); + return ret; +} From patchwork Wed Jun 30 15:47:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 12352495 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 18A05C11F6C for ; Wed, 30 Jun 2021 15:47:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EF73361477 for ; Wed, 30 Jun 2021 15:47:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235884AbhF3PuC (ORCPT ); Wed, 30 Jun 2021 11:50:02 -0400 Received: from mail.kernel.org ([198.145.29.99]:59422 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235889AbhF3PuA (ORCPT ); Wed, 30 Jun 2021 11:50:00 -0400 Received: from gandalf.local.home (cpe-66-24-58-225.stny.res.rr.com [66.24.58.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2DC9761466; Wed, 30 Jun 2021 15:47:31 +0000 (UTC) Received: from rostedt by gandalf.local.home with local (Exim 4.94.2) (envelope-from ) id 1lycR0-000Xoe-33; Wed, 30 Jun 2021 11:47:30 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: "Steven Rostedt (VMware)" Subject: [PATCH v2 4/4] libtracefs: Implement tracefs_kprobe_clear_probe() Date: Wed, 30 Jun 2021 11:47:29 -0400 Message-Id: <20210630154729.129873-5-rostedt@goodmis.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210630154729.129873-1-rostedt@goodmis.org> References: <20210630154729.129873-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (VMware)" Add the function tracefs_kprobe_clear_probe() that will remove a single kprobe. If the @force parameter is set, it will disable that probe in all instances (including the top level instance) before removing it. Signed-off-by: Steven Rostedt (VMware) --- include/tracefs.h | 1 + src/tracefs-kprobes.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/include/tracefs.h b/include/tracefs.h index 19b9b49d2dae..d7980c773b3d 100644 --- a/include/tracefs.h +++ b/include/tracefs.h @@ -218,4 +218,5 @@ void tracefs_trace_pipe_stop(struct tracefs_instance *instance); int tracefs_kprobe_raw(const char *system, const char *event, const char *addr, const char *format); int tracefs_kprobe_clear(bool force); +int tracefs_kprobe_clear_probe(const char *system, const char *event, bool force); #endif /* _TRACE_FS_H */ diff --git a/src/tracefs-kprobes.c b/src/tracefs-kprobes.c index a6faf69fc010..6f3fbac35d76 100644 --- a/src/tracefs-kprobes.c +++ b/src/tracefs-kprobes.c @@ -184,3 +184,32 @@ int tracefs_kprobe_clear(bool force) free(content); return ret; } + +int tracefs_kprobe_clear_probe(const char *system, const char *event, bool force) +{ + char **instance_list; + char *content; + int ret; + + if (!system) + system = "kprobes"; + + ret = asprintf(&content, "-:%s/%s", system, event); + if (ret < 0) + return -1; + + /* + * Since we know we are disabling a specific event, try + * to disable it first before clearing it. + */ + if (force) { + instance_list = tracefs_instances(NULL); + disable_events(system, event, instance_list); + tracefs_list_free(instance_list); + } + + ret = tracefs_instance_file_append(NULL, KPROBE_EVENTS, content); + free(content); + + return ret < 0 ? -1 : 0; +}