summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-23 19:59:29 +0300
committerPaul Buetow <paul@buetow.org>2026-05-23 19:59:29 +0300
commitb4a172404be8b52ed62171dcbbd3e9f46e36ac67 (patch)
treec92405f3843b6e743d32b7f899d54b26f6984d31 /internal
parent940bd6e00cb28af5f076828f6c90e6f3bc729cd8 (diff)
zb restore legacy -tps regex selection for non-FS tracepoints
When -tps provides an explicit regex but no -trace-* dimension selectors are given, skip the implicit FS-only syscall allowlist so that non-FS tracepoints (e.g. nanosleep) matched by the regex are still attached. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Diffstat (limited to 'internal')
-rw-r--r--internal/tracepoints/dimension_selector.go23
-rw-r--r--internal/tracepoints/dimension_selector_test.go80
2 files changed, 103 insertions, 0 deletions
diff --git a/internal/tracepoints/dimension_selector.go b/internal/tracepoints/dimension_selector.go
index 22a70fb..0ff32b3 100644
--- a/internal/tracepoints/dimension_selector.go
+++ b/internal/tracepoints/dimension_selector.go
@@ -19,14 +19,37 @@ type DimensionSelectorConfig struct {
NoTraceSyscalls string
}
+// hasAnySelector reports whether any positive or negative dimension selector
+// field is populated. When all fields are empty the caller provided no
+// -trace-* / -no-trace-* flags.
+func (d DimensionSelectorConfig) hasAnySelector() bool {
+ return d.TraceFamilies != "" ||
+ d.TraceKinds != "" ||
+ d.TraceSyscalls != "" ||
+ d.NoTraceFamilies != "" ||
+ d.NoTraceKinds != "" ||
+ d.NoTraceSyscalls != ""
+}
+
// ParseSelectorWithDimensions compiles regex-based attach/exclude filters and
// applies attach-time syscall dimension gating.
+//
+// Legacy semantics: when the caller supplies an explicit -tps regex but no
+// -trace-* / -no-trace-* dimension selectors, the syscall allowlist is skipped
+// entirely so that non-FS tracepoints matched by the regex are still attached.
func ParseSelectorWithDimensions(attach, exclude string, dims DimensionSelectorConfig) (Selector, error) {
sel, err := ParseSelector(attach, exclude)
if err != nil {
return Selector{}, err
}
+ // When an explicit -tps regex is provided without any dimension selectors,
+ // preserve legacy behaviour: the regex alone controls attachment and the
+ // implicit FS-only default is not applied.
+ if attach != "" && !dims.hasAnySelector() {
+ return sel, nil
+ }
+
allow, err := buildAllowedSyscalls(dims)
if err != nil {
return Selector{}, err
diff --git a/internal/tracepoints/dimension_selector_test.go b/internal/tracepoints/dimension_selector_test.go
index 01d48e7..39e24d6 100644
--- a/internal/tracepoints/dimension_selector_test.go
+++ b/internal/tracepoints/dimension_selector_test.go
@@ -313,3 +313,83 @@ func TestParseSelectorWithDimensionsRejectsInvalidSyscall(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
}
+
+func TestParseSelectorWithDimensionsRegexOnlyNanosleep(t *testing.T) {
+ // Regression: when -tps provides an explicit regex and no -trace-*
+ // dimension selectors are given, the implicit FS-only allowlist must not
+ // reject non-FS tracepoints such as nanosleep. Legacy regex-only
+ // semantics should let the regex control attachment.
+ sel, err := ParseSelectorWithDimensions(
+ "^sys_enter_nanosleep$,^sys_exit_nanosleep$", "",
+ DimensionSelectorConfig{},
+ )
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if !sel.ShouldAttach("sys_enter_nanosleep") {
+ t.Fatal("expected sys_enter_nanosleep to be attached by regex-only selector")
+ }
+ if !sel.ShouldAttach("sys_exit_nanosleep") {
+ t.Fatal("expected sys_exit_nanosleep to be attached by regex-only selector")
+ }
+ if sel.ShouldAttach("sys_enter_openat") {
+ t.Fatal("expected openat to be excluded by regex-only selector")
+ }
+}
+
+func TestParseSelectorWithDimensionsRegexPlusDimensionStillRestricts(t *testing.T) {
+ // When both a -tps regex and dimension selectors are provided, the
+ // dimension allowlist must still be enforced alongside the regex.
+ sel, err := ParseSelectorWithDimensions(
+ "^sys_enter_nanosleep$,^sys_exit_nanosleep$", "",
+ DimensionSelectorConfig{TraceFamilies: "Time"},
+ )
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if !sel.ShouldAttach("sys_enter_nanosleep") {
+ t.Fatal("expected nanosleep to pass both regex and Time family filter")
+ }
+ if sel.ShouldAttach("sys_enter_openat") {
+ t.Fatal("expected openat to be excluded by regex filter")
+ }
+}
+
+func TestParseSelectorWithDimensionsRegexOnlyExcludeStillWorks(t *testing.T) {
+ // When -tps is set with -tpsExclude but no dimension selectors, the
+ // exclude regex must still take effect.
+ sel, err := ParseSelectorWithDimensions(
+ "nanosleep", "sys_exit_nanosleep",
+ DimensionSelectorConfig{},
+ )
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if !sel.ShouldAttach("sys_enter_nanosleep") {
+ t.Fatal("expected sys_enter_nanosleep to be attached")
+ }
+ if sel.ShouldAttach("sys_exit_nanosleep") {
+ t.Fatal("expected sys_exit_nanosleep to be excluded by -tpsExclude regex")
+ }
+}
+
+func TestDimensionSelectorConfigHasAnySelector(t *testing.T) {
+ // Empty config has no selectors.
+ if (DimensionSelectorConfig{}).hasAnySelector() {
+ t.Fatal("expected empty config to report no selectors")
+ }
+ // Each individual field should count as a selector.
+ fields := []DimensionSelectorConfig{
+ {TraceFamilies: "FS"},
+ {TraceKinds: "sleep"},
+ {TraceSyscalls: "openat"},
+ {NoTraceFamilies: "FS"},
+ {NoTraceKinds: "sleep"},
+ {NoTraceSyscalls: "openat"},
+ }
+ for _, cfg := range fields {
+ if !cfg.hasAnySelector() {
+ t.Fatalf("expected config %+v to report selectors present", cfg)
+ }
+ }
+}