Skip to content

Commit b7dbc2e

Browse files
committed
Merge tag 'probes-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull probes updates from Masami Hiramatsu: "Stack usage reduction for probe events: - Allocate string buffers from the heap for uprobe, eprobe, kprobe, and fprobe events to avoid stack overflow - Allocate traceprobe_parse_context from the heap to prevent potential stack overflow - Fix a typo in the above commit New features for eprobe and tprobe events: - Add support for arrays in eprobes - Support multiple tprobes on the same tracepoint Improve efficiency: - Register fprobe-events only when it is enabled to reduce overhead - Register tracepoints for tprobe events only when enabled to resolve a lock dependency Code Cleanup: - Add kerneldoc for traceprobe_parse_event_name() and __get_insn_slot() - Sort #include alphabetically in the probes code - Remove the unused 'mod' field from the tprobe-event - Clean up the entry-arg storing code in probe-events Selftest update - Enable fprobe events before checking enable_functions in selftests" * tag 'probes-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing: trace_fprobe: Fix typo of the semicolon tracing: Have eprobes handle arrays tracing: probes: Add a kerneldoc for traceprobe_parse_event_name() tracing: uprobe-event: Allocate string buffers from heap tracing: eprobe-event: Allocate string buffers from heap tracing: kprobe-event: Allocate string buffers from heap tracing: fprobe-event: Allocate string buffers from heap tracing: probe: Allocate traceprobe_parse_context from heap tracing: probes: Sort #include alphabetically kprobes: Add missing kerneldoc for __get_insn_slot tracing: tprobe-events: Register tracepoint when enable tprobe event selftests: tracing: Enable fprobe events before checking enable_functions tracing: fprobe-events: Register fprobe-events only when it is enabled tracing: tprobe-events: Support multiple tprobes on the same tracepoint tracing: tprobe-events: Remove mod field from tprobe-event tracing: probe-events: Cleanup entry-arg storing code
2 parents a03eec7 + 133c302 commit b7dbc2e

File tree

11 files changed

+664
-341
lines changed

11 files changed

+664
-341
lines changed

include/linux/fprobe.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num);
9494
int register_fprobe_syms(struct fprobe *fp, const char **syms, int num);
9595
int unregister_fprobe(struct fprobe *fp);
9696
bool fprobe_is_registered(struct fprobe *fp);
97+
int fprobe_count_ips_from_filter(const char *filter, const char *notfilter);
9798
#else
9899
static inline int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter)
99100
{
@@ -115,6 +116,10 @@ static inline bool fprobe_is_registered(struct fprobe *fp)
115116
{
116117
return false;
117118
}
119+
static inline int fprobe_count_ips_from_filter(const char *filter, const char *notfilter)
120+
{
121+
return -EOPNOTSUPP;
122+
}
118123
#endif
119124

120125
/**

include/linux/module.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/buildid.h>
1515
#include <linux/compiler.h>
1616
#include <linux/cache.h>
17+
#include <linux/cleanup.h>
1718
#include <linux/kmod.h>
1819
#include <linux/init.h>
1920
#include <linux/elf.h>
@@ -1018,4 +1019,7 @@ static inline unsigned long find_kallsyms_symbol_value(struct module *mod,
10181019

10191020
#endif /* CONFIG_MODULES && CONFIG_KALLSYMS */
10201021

1022+
/* Define __free(module_put) macro for struct module *. */
1023+
DEFINE_FREE(module_put, struct module *, if (_T) module_put(_T))
1024+
10211025
#endif /* _LINUX_MODULE_H */

kernel/kprobes.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,12 @@ struct kprobe_insn_cache kprobe_insn_slots = {
135135
static int collect_garbage_slots(struct kprobe_insn_cache *c);
136136

137137
/**
138-
* __get_insn_slot() - Find a slot on an executable page for an instruction.
139-
* We allocate an executable page if there's no room on existing ones.
138+
* __get_insn_slot - Find a slot on an executable page for an instruction.
139+
* @c: Pointer to kprobe instruction cache
140+
*
141+
* Description: Locates available slot on existing executable pages,
142+
* allocates an executable page if there's no room on existing ones.
143+
* Return: Pointer to instruction slot on success, NULL on failure.
140144
*/
141145
kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
142146
{

kernel/trace/fprobe.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,11 @@ static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num)
648648

649649
#define FPROBE_IPS_MAX INT_MAX
650650

651+
int fprobe_count_ips_from_filter(const char *filter, const char *notfilter)
652+
{
653+
return get_ips_from_filter(filter, notfilter, NULL, NULL, FPROBE_IPS_MAX);
654+
}
655+
651656
/**
652657
* register_fprobe() - Register fprobe to ftrace by pattern.
653658
* @fp: A fprobe data structure to be registered.

kernel/trace/trace_eprobe.c

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
* Copyright (C) 2021, VMware Inc, Tzvetomir Stoyanov [email protected]>
1010
*
1111
*/
12+
#include <linux/cleanup.h>
13+
#include <linux/ftrace.h>
1214
#include <linux/module.h>
1315
#include <linux/mutex.h>
14-
#include <linux/ftrace.h>
1516

1617
#include "trace_dynevent.h"
1718
#include "trace_probe.h"
18-
#include "trace_probe_tmpl.h"
1919
#include "trace_probe_kernel.h"
20+
#include "trace_probe_tmpl.h"
2021

2122
#define EPROBE_EVENT_SYSTEM "eprobes"
2223

@@ -343,10 +344,15 @@ get_event_field(struct fetch_insn *code, void *rec)
343344
val = *(unsigned int *)addr;
344345
break;
345346
default:
346-
if (field->is_signed)
347-
val = *(long *)addr;
348-
else
349-
val = *(unsigned long *)addr;
347+
if (field->size == sizeof(long)) {
348+
if (field->is_signed)
349+
val = *(long *)addr;
350+
else
351+
val = *(unsigned long *)addr;
352+
break;
353+
}
354+
/* This is an array, point to the addr itself */
355+
val = (unsigned long)addr;
350356
break;
351357
}
352358
return val;
@@ -797,18 +803,20 @@ find_and_get_event(const char *system, const char *event_name)
797803

798804
static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[], int i)
799805
{
800-
struct traceprobe_parse_context ctx = {
801-
.event = ep->event,
802-
.flags = TPARG_FL_KERNEL | TPARG_FL_TEVENT,
803-
};
806+
struct traceprobe_parse_context *ctx __free(traceprobe_parse_context) = NULL;
804807
int ret;
805808

806-
ret = traceprobe_parse_probe_arg(&ep->tp, i, argv[i], &ctx);
809+
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
810+
if (!ctx)
811+
return -ENOMEM;
812+
ctx->event = ep->event;
813+
ctx->flags = TPARG_FL_KERNEL | TPARG_FL_TEVENT;
814+
815+
ret = traceprobe_parse_probe_arg(&ep->tp, i, argv[i], ctx);
807816
/* Handle symbols "@" */
808817
if (!ret)
809818
ret = traceprobe_update_arg(&ep->tp.args[i]);
810819

811-
traceprobe_finish_parse(&ctx);
812820
return ret;
813821
}
814822

@@ -869,10 +877,10 @@ static int __trace_eprobe_create(int argc, const char *argv[])
869877
const char *event = NULL, *group = EPROBE_EVENT_SYSTEM;
870878
const char *sys_event = NULL, *sys_name = NULL;
871879
struct trace_event_call *event_call;
880+
char *buf1 __free(kfree) = NULL;
881+
char *buf2 __free(kfree) = NULL;
882+
char *gbuf __free(kfree) = NULL;
872883
struct trace_eprobe *ep = NULL;
873-
char buf1[MAX_EVENT_NAME_LEN];
874-
char buf2[MAX_EVENT_NAME_LEN];
875-
char gbuf[MAX_EVENT_NAME_LEN];
876884
int ret = 0, filter_idx = 0;
877885
int i, filter_cnt;
878886

@@ -883,6 +891,9 @@ static int __trace_eprobe_create(int argc, const char *argv[])
883891

884892
event = strchr(&argv[0][1], ':');
885893
if (event) {
894+
gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
895+
if (!gbuf)
896+
goto mem_error;
886897
event++;
887898
ret = traceprobe_parse_event_name(&event, &group, gbuf,
888899
event - argv[0]);
@@ -892,14 +903,21 @@ static int __trace_eprobe_create(int argc, const char *argv[])
892903

893904
trace_probe_log_set_index(1);
894905
sys_event = argv[1];
906+
907+
buf2 = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
908+
if (!buf2)
909+
goto mem_error;
910+
895911
ret = traceprobe_parse_event_name(&sys_event, &sys_name, buf2, 0);
896912
if (ret || !sys_event || !sys_name) {
897913
trace_probe_log_err(0, NO_EVENT_INFO);
898914
goto parse_error;
899915
}
900916

901917
if (!event) {
902-
strscpy(buf1, sys_event, MAX_EVENT_NAME_LEN);
918+
buf1 = kstrdup(sys_event, GFP_KERNEL);
919+
if (!buf1)
920+
goto mem_error;
903921
event = buf1;
904922
}
905923

@@ -972,6 +990,9 @@ static int __trace_eprobe_create(int argc, const char *argv[])
972990
trace_probe_log_clear();
973991
return ret;
974992

993+
mem_error:
994+
ret = -ENOMEM;
995+
goto error;
975996
parse_error:
976997
ret = -EINVAL;
977998
error:

0 commit comments

Comments
 (0)