From f380f11a72ef4b0b87988cfffac753006a8dd444 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 29 Sep 2023 19:25:06 +0300 Subject: [PATCH 01/67] Add WithPID InstrumentationOption --- instConfig_test.go | 37 +++++++++++++++++++++++++++++++++++++ instrumentation.go | 29 ++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/instConfig_test.go b/instConfig_test.go index 24379c885..e00864e0e 100644 --- a/instConfig_test.go +++ b/instConfig_test.go @@ -17,6 +17,8 @@ package auto import ( "fmt" "os" + "strconv" + "strings" "testing" "github.com/stretchr/testify/assert" @@ -53,3 +55,38 @@ func TestWithServiceName(t *testing.T) { c = newInstConfig([]InstrumentationOption{WithServiceName((testServiceName))}) assert.Equal(t, envServiceName, c.serviceName) } + +func TestWithPID(t *testing.T) { + // Get a non existing PID + maxPIDBytes, err := os.ReadFile("/proc/sys/kernel/pid_max") + if err != nil { + t.Error(err) + } + + maxPID, err := strconv.Atoi(strings.TrimSuffix(string(maxPIDBytes), "\n")) + if err != nil { + t.Error(err) + } + + // Non existing PID + nonExistingPID := maxPID + 1 + c := newInstConfig([]InstrumentationOption{WithPID(nonExistingPID)}) + assert.Nil(t, c.target) + + // Current PID + currPID := os.Getpid() + c = newInstConfig([]InstrumentationOption{WithPID(currPID)}) + exe, err := os.Executable() + if err != nil { + t.Error(err) + } + assert.Equal(t, exe, c.target.ExePath) + + // Non existing PID but valid target should override it + c = newInstConfig([]InstrumentationOption{WithPID(nonExistingPID), WithTarget(exe)}) + assert.Equal(t, exe, c.target.ExePath) + + // Non valid target exe but valid PID - PID should override + c = newInstConfig([]InstrumentationOption{WithTarget("Non_Existing_Process"), WithPID(currPID)}) + assert.Equal(t, exe, c.target.ExePath) +} diff --git a/instrumentation.go b/instrumentation.go index c30d4791f..c5a7623c8 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -124,7 +124,9 @@ type instConfig struct { func newInstConfig(opts []InstrumentationOption) instConfig { var c instConfig for _, opt := range opts { - c = opt.apply(c) + if opt != nil { + c = opt.apply(c) + } } c = c.applyEnv() return c @@ -190,6 +192,9 @@ func (o fnOpt) apply(c instConfig) instConfig { return o(c) } // WithTarget returns an [InstrumentationOption] defining the target binary for // [Instrumentation] that is being executed at the provided path. // +// This option conflicts with [WithPID]. If both are used, the last one +// passed to [Instrumentation] will take precedence and be used. +// // If multiple of these options are provided to an [Instrumentation], the last // one will be used. // @@ -215,3 +220,25 @@ func WithServiceName(serviceName string) InstrumentationOption { return c }) } + +// WithPID returns an [InstrumentationOption] corresponding to the executable +// used by the provided pid. +// +// This option conflicts with [WithTarget]. If both are used, the last one +// passed to [Instrumentation] will take precedence and be used. +// +// If multiple of these options are provided to an [Instrumentation], the last +// one will be used. +// +// If OTEL_GO_AUTO_TARGET_EXE is defined it will take precedence over any value +// passed here. +func WithPID(pid int) InstrumentationOption { + exeLinkPath := fmt.Sprintf("/proc/%d/exe", pid) + exePath, err := os.Readlink(exeLinkPath) + if err != nil { + log.Logger.Error(err, "Failed to read exe link for process", "pid", pid) + return nil + } + + return WithTarget(exePath) +} From 2133ddd00885b8267f95f906410ac440b232acaf Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 29 Sep 2023 19:29:49 +0300 Subject: [PATCH 02/67] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b949c0557..a521c90d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http ### Added - Add `WithServiceName` config option for instrumentation. ([#353](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/353)) +- Add `WithPID` config option for instrumentation. ([#355](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/355)) ### Changed From b7fa23dc3e3e5ada3341d8681a1f671afa9952df Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 30 Sep 2023 18:36:00 +0300 Subject: [PATCH 03/67] Improve validation for inst config --- instConfig_test.go | 34 +++++----------------------- instrumentation.go | 38 +++++++++++++++++--------------- internal/pkg/process/args.go | 36 +++++++++++++++++++++--------- internal/pkg/process/discover.go | 3 +++ 4 files changed, 55 insertions(+), 56 deletions(-) diff --git a/instConfig_test.go b/instConfig_test.go index e00864e0e..c520c5258 100644 --- a/instConfig_test.go +++ b/instConfig_test.go @@ -17,8 +17,6 @@ package auto import ( "fmt" "os" - "strconv" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -57,36 +55,16 @@ func TestWithServiceName(t *testing.T) { } func TestWithPID(t *testing.T) { - // Get a non existing PID - maxPIDBytes, err := os.ReadFile("/proc/sys/kernel/pid_max") - if err != nil { - t.Error(err) - } - - maxPID, err := strconv.Atoi(strings.TrimSuffix(string(maxPIDBytes), "\n")) - if err != nil { - t.Error(err) - } - - // Non existing PID - nonExistingPID := maxPID + 1 - c := newInstConfig([]InstrumentationOption{WithPID(nonExistingPID)}) - assert.Nil(t, c.target) - // Current PID currPID := os.Getpid() - c = newInstConfig([]InstrumentationOption{WithPID(currPID)}) - exe, err := os.Executable() + c := newInstConfig([]InstrumentationOption{WithPID(currPID)}) + currExe, err := os.Executable() if err != nil { t.Error(err) } - assert.Equal(t, exe, c.target.ExePath) - - // Non existing PID but valid target should override it - c = newInstConfig([]InstrumentationOption{WithPID(nonExistingPID), WithTarget(exe)}) - assert.Equal(t, exe, c.target.ExePath) + assert.Equal(t, currPID, c.target.Pid) - // Non valid target exe but valid PID - PID should override - c = newInstConfig([]InstrumentationOption{WithTarget("Non_Existing_Process"), WithPID(currPID)}) - assert.Equal(t, exe, c.target.ExePath) + // PID should override valid target exe + c = newInstConfig([]InstrumentationOption{WithPID(currPID), WithTarget(currExe)}) + assert.Equal(t, currPID, c.target.Pid) } diff --git a/instrumentation.go b/instrumentation.go index c5a7623c8..90daf8fb1 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -50,8 +50,8 @@ type Instrumentation struct { manager *instrumentors.Manager } -// Error message returned when instrumentation is launched without a target -// binary. +// Error message returned when instrumentation is launched without a valid target +// binary or pid. var errUndefinedTarget = fmt.Errorf("undefined target Go binary, consider setting the %s environment variable pointing to the target binary to instrument", envTargetExeKey) // NewInstrumentation returns a new [Instrumentation] configured with the @@ -192,8 +192,8 @@ func (o fnOpt) apply(c instConfig) instConfig { return o(c) } // WithTarget returns an [InstrumentationOption] defining the target binary for // [Instrumentation] that is being executed at the provided path. // -// This option conflicts with [WithPID]. If both are used, the last one -// passed to [Instrumentation] will take precedence and be used. +// This option conflicts with [WithPID]. If both are used, [WithPID] will take +// precedence and be used. // // If multiple of these options are provided to an [Instrumentation], the last // one will be used. @@ -202,7 +202,11 @@ func (o fnOpt) apply(c instConfig) instConfig { return o(c) } // passed here. func WithTarget(path string) InstrumentationOption { return fnOpt(func(c instConfig) instConfig { - c.target = &process.TargetArgs{ExePath: path} + if c.target == nil { + c.target = &process.TargetArgs{ExePath: path} + } else { + c.target.ExePath = path + } return c }) } @@ -224,21 +228,19 @@ func WithServiceName(serviceName string) InstrumentationOption { // WithPID returns an [InstrumentationOption] corresponding to the executable // used by the provided pid. // -// This option conflicts with [WithTarget]. If both are used, the last one -// passed to [Instrumentation] will take precedence and be used. +// This option conflicts with [WithTarget]. If both are used, [WithPID] +// will take precedence and be used. If OTEL_GO_AUTO_TARGET_EXE is defined, +// the pid passed here will take precedence. // // If multiple of these options are provided to an [Instrumentation], the last // one will be used. -// -// If OTEL_GO_AUTO_TARGET_EXE is defined it will take precedence over any value -// passed here. func WithPID(pid int) InstrumentationOption { - exeLinkPath := fmt.Sprintf("/proc/%d/exe", pid) - exePath, err := os.Readlink(exeLinkPath) - if err != nil { - log.Logger.Error(err, "Failed to read exe link for process", "pid", pid) - return nil - } - - return WithTarget(exePath) + return fnOpt(func(c instConfig) instConfig { + if c.target == nil { + c.target = &process.TargetArgs{Pid: pid} + } else { + c.target.Pid = pid + } + return c + }) } diff --git a/internal/pkg/process/args.go b/internal/pkg/process/args.go index ad0c60e9a..a3e4c6d60 100644 --- a/internal/pkg/process/args.go +++ b/internal/pkg/process/args.go @@ -16,7 +16,9 @@ package process import ( "errors" + "fmt" "os" + "syscall" ) // ExePathEnvVar is the environment variable key whose value points to the @@ -26,26 +28,40 @@ const ExePathEnvVar = "OTEL_GO_AUTO_TARGET_EXE" // TargetArgs are the binary target information. type TargetArgs struct { ExePath string + Pid int } // Validate validates t and returns an error if not valid. func (t *TargetArgs) Validate() error { + if t.Pid != 0 { + return validatePID(t.Pid) + } if t.ExePath == "" { return errors.New("target binary path not specified, please specify " + ExePathEnvVar + " env variable") } - return nil + return validateExePath(t.ExePath) } -// ParseTargetArgs returns TargetArgs for the target pointed to by the -// environment variable OTEL_GO_AUTO_TARGET_EXE. -func ParseTargetArgs() *TargetArgs { - result := &TargetArgs{} - - val, exists := os.LookupEnv(ExePathEnvVar) - if exists { - result.ExePath = val +func validateExePath(exePath string) error { + info, err := os.Stat(exePath) + if err != nil { + return errors.New(exePath + "does not exist") } + if info.Mode().Perm()&0o111 == 0 { + return errors.New(exePath + "is not executable") + } + return nil +} - return result +func validatePID(pid int) error { + p, err := os.FindProcess(pid) + if err != nil { + return fmt.Errorf("can't find process with pid %d", pid) + } + err = p.Signal(syscall.Signal(0)) + if err != nil { + return fmt.Errorf("process with pid %d does not exist", pid) + } + return nil } diff --git a/internal/pkg/process/discover.go b/internal/pkg/process/discover.go index dbc9b766a..9a63832bc 100644 --- a/internal/pkg/process/discover.go +++ b/internal/pkg/process/discover.go @@ -43,6 +43,9 @@ func NewAnalyzer() *Analyzer { // DiscoverProcessID searches for the target as an actively running process, // returning its PID if found. func (a *Analyzer) DiscoverProcessID(target *TargetArgs) (int, error) { + if target.Pid != 0 { + return target.Pid, nil + } for { select { case <-a.done: From 254a80b70aec0806efbad697105c4edc04037717 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 30 Sep 2023 21:13:03 +0300 Subject: [PATCH 04/67] WIP --- instrumentation.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/instrumentation.go b/instrumentation.go index 90daf8fb1..403ab8e95 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -134,7 +134,9 @@ func newInstConfig(opts []InstrumentationOption) instConfig { func (c instConfig) applyEnv() instConfig { if v, ok := os.LookupEnv(envTargetExeKey); ok { - c.target = &process.TargetArgs{ExePath: v} + if c.target == nil || (c.target != nil && c.target.Pid == 0) { + c.target = &process.TargetArgs{ExePath: v} + } } if v, ok := os.LookupEnv(envServiceNameKey); ok { c.serviceName = v From f93f386d01823b3f56ccf3b648da3306206729c2 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 1 Oct 2023 14:34:03 +0300 Subject: [PATCH 05/67] more WIP --- instrumentation.go | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/instrumentation.go b/instrumentation.go index 403ab8e95..45771d902 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -122,7 +122,7 @@ type instConfig struct { } func newInstConfig(opts []InstrumentationOption) instConfig { - var c instConfig + var c instConfig = instConfig{target: &process.TargetArgs{}} for _, opt := range opts { if opt != nil { c = opt.apply(c) @@ -134,9 +134,7 @@ func newInstConfig(opts []InstrumentationOption) instConfig { func (c instConfig) applyEnv() instConfig { if v, ok := os.LookupEnv(envTargetExeKey); ok { - if c.target == nil || (c.target != nil && c.target.Pid == 0) { - c.target = &process.TargetArgs{ExePath: v} - } + c.target.ExePath = v } if v, ok := os.LookupEnv(envServiceNameKey); ok { c.serviceName = v @@ -150,7 +148,7 @@ func (c instConfig) applyEnv() instConfig { } func (c instConfig) setDefualtServiceName() instConfig { - if c.target != nil { + if c.target.ExePath != "" { c.serviceName = fmt.Sprintf("%s:%s", serviceNameDefault, filepath.Base(c.target.ExePath)) } else { c.serviceName = serviceNameDefault @@ -204,11 +202,7 @@ func (o fnOpt) apply(c instConfig) instConfig { return o(c) } // passed here. func WithTarget(path string) InstrumentationOption { return fnOpt(func(c instConfig) instConfig { - if c.target == nil { - c.target = &process.TargetArgs{ExePath: path} - } else { - c.target.ExePath = path - } + c.target.ExePath = path return c }) } @@ -238,11 +232,7 @@ func WithServiceName(serviceName string) InstrumentationOption { // one will be used. func WithPID(pid int) InstrumentationOption { return fnOpt(func(c instConfig) instConfig { - if c.target == nil { - c.target = &process.TargetArgs{Pid: pid} - } else { - c.target.Pid = pid - } + c.target.Pid = pid return c }) } From 4470cb6ea4600043c816c19d48f0c70ffbcfc4d0 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 1 Oct 2023 17:19:05 +0300 Subject: [PATCH 06/67] Remove exePath checks --- Makefile | 12 ++++++++---- instrumentation.go | 2 +- internal/pkg/process/args.go | 12 +----------- internal/test/e2e/nethttp/traces-orig.json | 1 + 4 files changed, 11 insertions(+), 16 deletions(-) create mode 100644 internal/test/e2e/nethttp/traces-orig.json diff --git a/Makefile b/Makefile index 8ff23ff45..2bb65ec3f 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,10 @@ generate: docker-generate: docker run --rm -v $(shell pwd):/app golang:1.20 /bin/sh -c "apt-get update && apt-get install -y clang llvm libbpf-dev && cd ../app && make generate" +.PHONY: docker-test +docker-test: + docker run --rm -v $(shell pwd):/app golang:1.20 /bin/sh -c "apt-get update && apt-get install -y clang llvm libbpf-dev && cd ../app && make test" + .PHONY: go-mod-tidy go-mod-tidy: $(ALL_GO_MOD_DIRS:%=go-mod-tidy/%) go-mod-tidy/%: DIR=$* @@ -145,7 +149,7 @@ fixture-databasesql: fixtures/databasesql fixtures/%: LIBRARY=$* fixtures/%: $(MAKE) docker-build - cd test/e2e/$(LIBRARY) && docker build -t sample-app . + cd internal/test/e2e/$(LIBRARY) && docker build -t sample-app . kind create cluster kind load docker-image otel-go-instrumentation sample-app helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts @@ -156,9 +160,9 @@ fixtures/%: kubectl wait --for=condition=Ready --timeout=60s pod/test-opentelemetry-collector-0 kubectl -n default create -f .github/workflows/e2e/k8s/sample-job.yml kubectl wait --for=condition=Complete --timeout=60s job/sample-job - kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/$(LIBRARY)/traces-orig.json - rm -f ./test/e2e/$(LIBRARY)/traces.json - bats ./test/e2e/$(LIBRARY)/verify.bats + kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./internal/test/e2e/$(LIBRARY)/traces-orig.json + rm -f ./internal/test/e2e/$(LIBRARY)/traces.json + bats ./internal/test/e2e/$(LIBRARY)/verify.bats kind delete cluster .PHONY: prerelease diff --git a/instrumentation.go b/instrumentation.go index 45771d902..628cf5ba1 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -122,7 +122,7 @@ type instConfig struct { } func newInstConfig(opts []InstrumentationOption) instConfig { - var c instConfig = instConfig{target: &process.TargetArgs{}} + var c = instConfig{target: &process.TargetArgs{}} for _, opt := range opts { if opt != nil { c = opt.apply(c) diff --git a/internal/pkg/process/args.go b/internal/pkg/process/args.go index a3e4c6d60..ef2c28635 100644 --- a/internal/pkg/process/args.go +++ b/internal/pkg/process/args.go @@ -40,20 +40,10 @@ func (t *TargetArgs) Validate() error { return errors.New("target binary path not specified, please specify " + ExePathEnvVar + " env variable") } - return validateExePath(t.ExePath) -} - -func validateExePath(exePath string) error { - info, err := os.Stat(exePath) - if err != nil { - return errors.New(exePath + "does not exist") - } - if info.Mode().Perm()&0o111 == 0 { - return errors.New(exePath + "is not executable") - } return nil } + func validatePID(pid int) error { p, err := os.FindProcess(pid) if err != nil { diff --git a/internal/test/e2e/nethttp/traces-orig.json b/internal/test/e2e/nethttp/traces-orig.json new file mode 100644 index 000000000..8a3278ecf --- /dev/null +++ b/internal/test/e2e/nethttp/traces-orig.json @@ -0,0 +1 @@ +{"resourceSpans":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"sample-app"}},{"key":"telemetry.auto.version","value":{"stringValue":"v0.3.0-alpha"}},{"key":"telemetry.sdk.language","value":{"stringValue":"go"}}]},"scopeSpans":[{"scope":{"name":"net/http"},"spans":[{"traceId":"17adc4a54489628b651a4b0c623ad067","spanId":"a405d8b0ec3191e9","parentSpanId":"f073753f66f5a069","name":"GET","kind":2,"startTimeUnixNano":"1696169828489942347","endTimeUnixNano":"1696169828489976055","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.target","value":{"stringValue":"/hello"}}],"status":{}}]},{"scope":{"name":"net/http/client"},"spans":[{"traceId":"17adc4a54489628b651a4b0c623ad067","spanId":"f073753f66f5a069","parentSpanId":"","name":"/hello","kind":3,"startTimeUnixNano":"1696169828487591305","endTimeUnixNano":"1696169828490389513","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.target","value":{"stringValue":"/hello"}}],"status":{}}]}]}]} From 00d0226cdfc86f1a742d7ec760082f34d3b8dbfa Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 1 Oct 2023 17:36:08 +0300 Subject: [PATCH 07/67] Fix lint --- internal/pkg/process/args.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/pkg/process/args.go b/internal/pkg/process/args.go index ef2c28635..0769b0dda 100644 --- a/internal/pkg/process/args.go +++ b/internal/pkg/process/args.go @@ -43,7 +43,6 @@ func (t *TargetArgs) Validate() error { return nil } - func validatePID(pid int) error { p, err := os.FindProcess(pid) if err != nil { From d82ad0a353c81d7dab84bc92a7b7e41578be5070 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 1 Oct 2023 17:57:20 +0300 Subject: [PATCH 08/67] remove traces-orig.json --- .gitignore | 2 +- internal/test/e2e/nethttp/traces-orig.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 internal/test/e2e/nethttp/traces-orig.json diff --git a/.gitignore b/.gitignore index b64131b13..4f8a796a6 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ launcher/ opentelemetry-helm-charts/ # don't track temp e2e trace json files -test/**/traces-orig.json +internal/test/**/traces-orig.json # ignore db files created by the example or tests *.db \ No newline at end of file diff --git a/internal/test/e2e/nethttp/traces-orig.json b/internal/test/e2e/nethttp/traces-orig.json deleted file mode 100644 index 8a3278ecf..000000000 --- a/internal/test/e2e/nethttp/traces-orig.json +++ /dev/null @@ -1 +0,0 @@ -{"resourceSpans":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"sample-app"}},{"key":"telemetry.auto.version","value":{"stringValue":"v0.3.0-alpha"}},{"key":"telemetry.sdk.language","value":{"stringValue":"go"}}]},"scopeSpans":[{"scope":{"name":"net/http"},"spans":[{"traceId":"17adc4a54489628b651a4b0c623ad067","spanId":"a405d8b0ec3191e9","parentSpanId":"f073753f66f5a069","name":"GET","kind":2,"startTimeUnixNano":"1696169828489942347","endTimeUnixNano":"1696169828489976055","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.target","value":{"stringValue":"/hello"}}],"status":{}}]},{"scope":{"name":"net/http/client"},"spans":[{"traceId":"17adc4a54489628b651a4b0c623ad067","spanId":"f073753f66f5a069","parentSpanId":"","name":"/hello","kind":3,"startTimeUnixNano":"1696169828487591305","endTimeUnixNano":"1696169828490389513","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.target","value":{"stringValue":"/hello"}}],"status":{}}]}]}]} From b087541199cf9458962fd7613c19269f855b0ecb Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 1 Oct 2023 17:59:42 +0300 Subject: [PATCH 09/67] . --- instrumentation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation.go b/instrumentation.go index 628cf5ba1..43e949149 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -122,7 +122,7 @@ type instConfig struct { } func newInstConfig(opts []InstrumentationOption) instConfig { - var c = instConfig{target: &process.TargetArgs{}} + c := instConfig{target: &process.TargetArgs{}} for _, opt := range opts { if opt != nil { c = opt.apply(c) From a171403b977877d89c3f6e616107563a5fe3c7ff Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Mon, 2 Oct 2023 10:21:14 +0300 Subject: [PATCH 10/67] Init log if not initialized in NewInstrumentation --- instrumentation.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/instrumentation.go b/instrumentation.go index 43e949149..b132d261f 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -83,6 +83,15 @@ func NewInstrumentation(opts ...InstrumentationOption) (*Instrumentation, error) mngr.Close() return nil, err } + + if log.Logger.IsZero() { + err := log.Init() + if err != nil { + fmt.Printf("could not init logger: %s\n", err) + os.Exit(1) + } + } + log.Logger.V(0).Info( "target process analysis completed", "pid", td.PID, From aae2823d741f5b66b41f700f0962cb276b4eba74 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Mon, 2 Oct 2023 13:52:56 +0300 Subject: [PATCH 11/67] fix os.Exit --- instrumentation.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/instrumentation.go b/instrumentation.go index b132d261f..5e9c1eb11 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -87,8 +87,7 @@ func NewInstrumentation(opts ...InstrumentationOption) (*Instrumentation, error) if log.Logger.IsZero() { err := log.Init() if err != nil { - fmt.Printf("could not init logger: %s\n", err) - os.Exit(1) + return nil, err } } From 4b072cd030a62c306a27364727e50e3e710cfcac Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Mon, 2 Oct 2023 17:06:54 +0300 Subject: [PATCH 12/67] test --- internal/pkg/process/analyze.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index 4738990ec..e39e08f17 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -19,6 +19,7 @@ import ( "errors" "fmt" "os" + "runtime" "github.com/hashicorp/go-version" @@ -84,6 +85,8 @@ func (t *TargetDetails) GetFunctionReturns(name string) ([]uint64, error) { } func (a *Analyzer) remoteMmap(pid int, mapSize uint64) (uint64, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() program, err := ptrace.NewTracedProgram(pid, log.Logger) if err != nil { log.Logger.Error(err, "Failed to attach ptrace", "pid", pid) From 8dd135b7cc580d85d3a312875883fd20639a054a Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 3 Oct 2023 09:38:53 +0300 Subject: [PATCH 13/67] Test Madvise --- internal/pkg/instrumentors/utils/kernel.go | 28 +++++++++++++++++++++ internal/pkg/process/analyze.go | 13 +++++----- internal/pkg/process/ptrace/ptrace_linux.go | 28 ++++++++++++++++++++- 3 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 internal/pkg/instrumentors/utils/kernel.go diff --git a/internal/pkg/instrumentors/utils/kernel.go b/internal/pkg/instrumentors/utils/kernel.go new file mode 100644 index 000000000..b5b1c8206 --- /dev/null +++ b/internal/pkg/instrumentors/utils/kernel.go @@ -0,0 +1,28 @@ +package utils + +import ( + "strings" + "syscall" + + "github.com/hashicorp/go-version" +) + +func GetLinuxKernelVersion() (*version.Version, error) { + var utsname syscall.Utsname + + if err := syscall.Uname(&utsname); err != nil { + return nil, err + } + + var buf [65]byte + for i, v := range utsname.Release { + buf[i] = byte(v) + } + + ver := string(buf[:]) + if strings.Contains(ver, "-") { + ver = strings.Split(ver, "-")[0] + } + + return version.NewVersion(ver) +} \ No newline at end of file diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index e39e08f17..503dbdfa8 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -27,12 +27,6 @@ import ( "go.opentelemetry.io/auto/internal/pkg/process/ptrace" ) -const ( - // The concurrent trace & span ID pairs lookup size in bytes. Currently set to 24mb. - // TODO: Review map size. - mapSize = 25165824 -) - // TargetDetails are the details about a target function. type TargetDetails struct { PID int @@ -107,6 +101,12 @@ func (a *Analyzer) remoteMmap(pid int, mapSize uint64) (uint64, error) { return 0, err } + err = program.Madvise(addr, mapSize) + if err != nil { + log.Logger.Error(err, "Failed to madvise", "pid", pid) + return 0, err + } + return addr, nil } @@ -134,6 +134,7 @@ func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*Targ result.GoVersion = goVersion result.Libraries = modules + mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 50) addr, err := a.remoteMmap(pid, mapSize) if err != nil { log.Logger.Error(err, "Failed to mmap") diff --git a/internal/pkg/process/ptrace/ptrace_linux.go b/internal/pkg/process/ptrace/ptrace_linux.go index f1a2088a6..39c8cc27a 100644 --- a/internal/pkg/process/ptrace/ptrace_linux.go +++ b/internal/pkg/process/ptrace/ptrace_linux.go @@ -23,10 +23,18 @@ import ( "github.com/go-logr/logr" "github.com/pkg/errors" + "go.opentelemetry.io/auto/internal/pkg/instrumentors/utils" + "github.com/hashicorp/go-version" + "go.opentelemetry.io/auto/internal/pkg/log" ) const waitPidErrorMessage = "waitpid ret value: %d" +const ( + MADV_POPULATE_READ = 0x16 + MADV_POPULATE_WRITE = 0x17 +) + var threadRetryLimit = 10 // TracedProgram is a program traced by ptrace. @@ -207,5 +215,23 @@ func (p *TracedProgram) Step() error { // Mmap runs mmap syscall. func (p *TracedProgram) Mmap(length uint64, fd uint64) (uint64, error) { - return p.Syscall(syscall.SYS_MMAP, 0, length, syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC, syscall.MAP_ANON|syscall.MAP_PRIVATE|syscall.MAP_POPULATE, fd, 0) + return p.Syscall(syscall.SYS_MMAP, 0, length, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE|syscall.MAP_POPULATE|syscall.MAP_LOCKED, fd, 0) } + +// Madvise runs madvise syscall. +func (p *TracedProgram) Madvise(addr uint64, length uint64) error { + advice := uint64(syscall.MADV_WILLNEED) + ver, err := utils.GetLinuxKernelVersion() + if err != nil { + return errors.WithStack(err) + } + + minVersion := version.Must(version.NewVersion("5.14")) + log.Logger.V(0).Info("Detected linux kernel version", "version", ver) + if ver.GreaterThanOrEqual(minVersion) { + advice = syscall.MADV_WILLNEED | MADV_POPULATE_WRITE | MADV_POPULATE_READ + } + + _, err = p.Syscall(syscall.SYS_MADVISE, addr, length, advice, 0, 0, 0) + return err +} \ No newline at end of file From d34c19ff2c9a3960c0bcadd6c55bb3c8988fe830 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 3 Oct 2023 11:25:06 +0300 Subject: [PATCH 14/67] More testing --- internal/include/alloc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/include/alloc.h b/internal/include/alloc.h index df069533c..d2cff0610 100644 --- a/internal/include/alloc.h +++ b/internal/include/alloc.h @@ -114,6 +114,7 @@ static __always_inline void *write_target_data(void *data, s32 size) } bpf_map_update_elem(&alloc_map, &start_index, &updated_start, BPF_ANY); + bpf_printk("wrote %d bytes to userspace at addr: %lx", size, target); return target; } else From 0a7acd200625e2d93a0d4b065153d44b99c11ac6 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 3 Oct 2023 13:36:32 +0300 Subject: [PATCH 15/67] More testing... --- internal/include/go_types.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/internal/include/go_types.h b/internal/include/go_types.h index cf18fffa8..f828279ba 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -56,13 +56,17 @@ struct map_bucket { static __always_inline struct go_string write_user_go_string(char *str, u32 len) { + struct go_string new_string = {.str = NULL, .len = 0}; + // Copy chars to userspace char *addr = write_target_data((void *)str, len); - - // Build string struct in kernel space - struct go_string new_string = {}; - new_string.str = addr; - new_string.len = len; + if (addr == NULL) { + return new_string; + } else { + // Build string struct in kernel space + new_string.str = addr; + new_string.len = len; + } // Copy new string struct to userspace void *res = write_target_data((void *)&new_string, sizeof(new_string)); @@ -111,6 +115,11 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n } void *new_array = write_target_data(map_buff, new_array_size); + if (new_array == NULL) + { + bpf_printk("append_item_to_slice: failed to copy new array to userspace"); + return; + } // Update array slice->array = new_array; From f9125e235f2f2a0a4e2e2a3f87a94f129950be7a Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 3 Oct 2023 17:04:49 +0300 Subject: [PATCH 16/67] .... --- internal/include/go_types.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/include/go_types.h b/internal/include/go_types.h index f828279ba..f1d080ee2 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -81,11 +81,13 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n { if (slice->len < slice->cap) { + bpf_printk("room aviailable on current array"); // Room available on current array bpf_probe_write_user(slice->array + (item_size * slice->len), new_item, item_size); } else { + bpf_printk("no room on current array"); // No room on current array - copy to new one of size item_size * (len + 1) if (slice->len > MAX_DATA_SIZE || slice->len < 1) { @@ -124,6 +126,11 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n // Update array slice->array = new_array; long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array)); + if (success != 0) + { + bpf_printk("append_item_to_slice: failed to update slice array"); + return; + } // Update cap slice->cap++; From fd73a5c3d84d1bfa29d97248f9c7b5b778149ebb Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 3 Oct 2023 17:33:06 +0300 Subject: [PATCH 17/67] ,,,,, --- .../instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index ab7986e87..3f1540209 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -111,8 +111,8 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) // Get parent if exists void *context_ptr = get_argument(ctx, context_pos); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + // void *context_ptr_val = 0; + // bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); if (parent_span_ctx != NULL) { From 41b4d9ccd946554db7a3c0196b61779ef1944da9 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 3 Oct 2023 17:39:16 +0300 Subject: [PATCH 18/67] .... --- .../instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 3f1540209..0edf7f903 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -109,7 +109,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) target_size = target_size < target_len ? target_size : target_len; bpf_probe_read(&grpcReq.target, target_size, target_ptr); - // Get parent if exists + // Get parent if exists void *context_ptr = get_argument(ctx, context_pos); // void *context_ptr_val = 0; // bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); From 3e6b20f637fc80489c910ad88095c3f92cac9464 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 3 Oct 2023 22:07:31 +0300 Subject: [PATCH 19/67] fix compilation --- .../instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 0edf7f903..6fe4dfa2a 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -113,7 +113,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) void *context_ptr = get_argument(ctx, context_pos); // void *context_ptr_val = 0; // bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); - struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); + struct span_context *parent_span_ctx = get_parent_span_context(context_ptr); if (parent_span_ctx != NULL) { bpf_probe_read(&grpcReq.psc, sizeof(grpcReq.psc), parent_span_ctx); From 8aa390bacf52d3dcbcab23f9d54c9cdaa393f104 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 4 Oct 2023 09:00:39 +0300 Subject: [PATCH 20/67] context_ptr fix --- .../bpf/google.golang.org/grpc/bpf/probe.bpf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 6fe4dfa2a..3975d291a 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -130,7 +130,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) // Write event bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); - start_tracking_span(context_ptr_val, &grpcReq.sc); + start_tracking_span(context_ptr, &grpcReq.sc); return 0; } @@ -185,14 +185,14 @@ SEC("uprobe/http2Client_NewStream") int uprobe_http2Client_NewStream(struct pt_regs *ctx) { void *context_ptr = get_argument(ctx, 3); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + // void *context_ptr_val = 0; + // bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); void *httpclient_ptr = get_argument(ctx, 1); u32 nextid = 0; bpf_probe_read(&nextid, sizeof(nextid), (void *)(httpclient_ptr + (httpclient_nextid_pos))); - struct span_context *current_span_context = get_parent_span_context(context_ptr_val); + struct span_context *current_span_context = get_parent_span_context(context_ptr); if (current_span_context != NULL) { bpf_map_update_elem(&streamid_to_span_contexts, &nextid, current_span_context, 0); } From b4066bf52a3ad21e2ab6f292367c0ae452e3ded6 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 4 Oct 2023 10:06:42 +0300 Subject: [PATCH 21/67] .,, --- internal/include/go_types.h | 28 +++++++++---------- .../google.golang.org/grpc/bpf/probe.bpf.c | 4 --- .../bpf/net/http/server/bpf/probe.bpf.c | 17 ++++++++++- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/internal/include/go_types.h b/internal/include/go_types.h index f1d080ee2..35a37ae09 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -54,20 +54,28 @@ struct map_bucket { void *overflow; }; -static __always_inline struct go_string write_user_go_string(char *str, u32 len) +// In Go, interfaces are represented as a pair of pointers: a pointer to the +// interface data, and a pointer to the interface table. +// See: runtime.iface in https://golang.org/src/runtime/runtime2.go +static __always_inline void* get_go_interface_instance(void *iface) { - struct go_string new_string = {.str = NULL, .len = 0}; + return (void*)(iface + 8); +} +static __always_inline struct go_string write_user_go_string(char *str, u32 len) +{ // Copy chars to userspace + struct go_string new_string = {.str = NULL, .len = 0}; char *addr = write_target_data((void *)str, len); if (addr == NULL) { + bpf_printk("write_user_go_string: failed to copy string to userspace"); return new_string; - } else { - // Build string struct in kernel space - new_string.str = addr; - new_string.len = len; } + // Build string struct in kernel space + new_string.str = addr; + new_string.len = len; + // Copy new string struct to userspace void *res = write_target_data((void *)&new_string, sizeof(new_string)); if (res == NULL) { @@ -81,13 +89,11 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n { if (slice->len < slice->cap) { - bpf_printk("room aviailable on current array"); // Room available on current array bpf_probe_write_user(slice->array + (item_size * slice->len), new_item, item_size); } else { - bpf_printk("no room on current array"); // No room on current array - copy to new one of size item_size * (len + 1) if (slice->len > MAX_DATA_SIZE || slice->len < 1) { @@ -126,11 +132,6 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n // Update array slice->array = new_array; long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array)); - if (success != 0) - { - bpf_printk("append_item_to_slice: failed to update slice array"); - return; - } // Update cap slice->cap++; @@ -141,5 +142,4 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n slice->len++; long success = bpf_probe_write_user(slice_user_ptr->len, &slice->len, sizeof(slice->len)); } - #endif \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 3975d291a..132c25fd1 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -185,13 +185,9 @@ SEC("uprobe/http2Client_NewStream") int uprobe_http2Client_NewStream(struct pt_regs *ctx) { void *context_ptr = get_argument(ctx, 3); - // void *context_ptr_val = 0; - // bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); - void *httpclient_ptr = get_argument(ctx, 1); u32 nextid = 0; bpf_probe_read(&nextid, sizeof(nextid), (void *)(httpclient_ptr + (httpclient_nextid_pos))); - struct span_context *current_span_context = get_parent_span_context(context_ptr); if (current_span_context != NULL) { bpf_map_update_elem(&streamid_to_span_contexts, &nextid, current_span_context, 0); diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 83e8f81d8..2c6650796 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -172,6 +172,11 @@ SEC("uprobe/ServerMux_ServeHTTP") int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) { u64 request_pos = 4; + void *req_ptr = get_argument(ctx, request_pos); + void *req_ctx_ptr = 0; + void *ctx_address = get_go_interface_instance(req_ptr + ctx_ptr_pos); + bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), ctx_address); + struct http_request_t httpReq = {}; httpReq.start_time = bpf_ktime_get_ns(); @@ -208,7 +213,17 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) } else { - httpReq.sc = generate_span_context(); + parent_ctx = get_parent_span_context(req_ctx_ptr); + if (parent_ctx != NULL) + { + httpReq.psc = *parent_ctx; + copy_byte_arrays(httpReq.psc.TraceID, httpReq.sc.TraceID, TRACE_ID_SIZE); + generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); + } + else + { + httpReq.sc = generate_span_context(); + } } // Get key From aa9d84f7f495a783eaa4ccf9c0c7a8383ffa8952 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 4 Oct 2023 10:25:44 +0300 Subject: [PATCH 22/67] . --- .../instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 2c6650796..dd927095f 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -172,6 +172,7 @@ SEC("uprobe/ServerMux_ServeHTTP") int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) { u64 request_pos = 4; + // Get request struct void *req_ptr = get_argument(ctx, request_pos); void *req_ctx_ptr = 0; void *ctx_address = get_go_interface_instance(req_ptr + ctx_ptr_pos); @@ -180,9 +181,6 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) struct http_request_t httpReq = {}; httpReq.start_time = bpf_ktime_get_ns(); - // Get request struct - void *req_ptr = get_argument(ctx, request_pos); - // Get method from request void *method_ptr = 0; bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr + method_ptr_pos)); @@ -207,6 +205,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) struct span_context *parent_ctx = extract_context_from_req_headers(req_ptr + headers_ptr_pos); if (parent_ctx != NULL) { + // found parent context in http headers httpReq.psc = *parent_ctx; copy_byte_arrays(httpReq.psc.TraceID, httpReq.sc.TraceID, TRACE_ID_SIZE); generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); @@ -227,9 +226,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) } // Get key - void *req_ctx_ptr = 0; - bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); - void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); + void *key = get_consistent_key(ctx, ctx_address); // Write event bpf_map_update_elem(&http_events, &key, &httpReq, 0); From c00e4076432b084682f805e423f06cbd73478ca3 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 4 Oct 2023 11:22:26 +0300 Subject: [PATCH 23/67] fix context propagation --- internal/include/go_context.h | 15 +++++++++------ internal/include/uprobe.h | 3 ++- .../bpf/net/http/server/bpf/probe.bpf.c | 12 +----------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 701fffd17..8b8dc0165 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -77,14 +77,17 @@ static __always_inline void start_tracking_span(void *ctx, struct span_context * bpf_map_update_elem(&tracked_spans_by_sc, sc, &ctx, BPF_ANY); } -static __always_inline void stop_tracking_span(struct span_context *sc) { - void *ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, sc); - if (ctx == NULL) +static __always_inline void stop_tracking_span(struct span_context *sc, bool isRoot) { + if (isRoot) { - return; - } + void *ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, sc); + if (ctx == NULL) + { + return; + } - bpf_map_delete_elem(&tracked_spans, &ctx); + bpf_map_delete_elem(&tracked_spans, ctx); + } bpf_map_delete_elem(&tracked_spans_by_sc, sc); } diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index d68cbacac..46eaf36f5 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -43,7 +43,8 @@ int uprobe_##name##_Returns(struct pt_regs *ctx) { tmpReq.end_time = bpf_ktime_get_ns(); \ bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ bpf_map_delete_elem(&uprobe_context_map, &key); \ - stop_tracking_span(&tmpReq.sc); \ + bool isRoot = (tmpReq.psc.TraceID[0] == 0); \ + stop_tracking_span(&tmpReq.sc, isRoot); \ return 0; \ } diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index dd927095f..7a70bddca 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -212,17 +212,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) } else { - parent_ctx = get_parent_span_context(req_ctx_ptr); - if (parent_ctx != NULL) - { - httpReq.psc = *parent_ctx; - copy_byte_arrays(httpReq.psc.TraceID, httpReq.sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); - } - else - { - httpReq.sc = generate_span_context(); - } + httpReq.sc = generate_span_context(); } // Get key From 2527b4edb66fd55fe33fa0aa3cfcea6106a68830 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 4 Oct 2023 13:57:31 +0300 Subject: [PATCH 24/67] Add padding --- internal/include/alloc.h | 41 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/internal/include/alloc.h b/internal/include/alloc.h index d2cff0610..1b0e5a029 100644 --- a/internal/include/alloc.h +++ b/internal/include/alloc.h @@ -35,6 +35,15 @@ struct __uint(pinning, LIBBPF_PIN_BY_NAME); } alloc_map SEC(".maps"); +// Buffer for aligned data +struct +{ + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __uint(key_size, sizeof(u32)); + __uint(value_size, MAX_BUFFER_SIZE); + __uint(max_entries, 1); +} alignment_buffer SEC(".maps"); + static __always_inline u64 get_area_start() { s64 partition_size = (end_addr - start_addr) / total_cpus; @@ -44,6 +53,9 @@ static __always_inline u64 get_area_start() if (start == NULL || *start == 0) { u64 current_start_addr = start_addr + (partition_size * current_cpu); + if (current_start_addr % 8 != 0) { + current_start_addr += 8 - (current_start_addr % 8); + } bpf_map_update_elem(&alloc_map, &start_index, ¤t_start_addr, BPF_ANY); return current_start_addr; } @@ -90,6 +102,29 @@ static __always_inline void *write_target_data(void *data, s32 size) return NULL; } + // Add padding to align to 8 bytes + if (size % 8 != 0) { + size += 8 - (size % 8); + + // Write to the buffer + u32 key = 0; + void *buffer = bpf_map_lookup_elem(&alignment_buffer, &key); + if (buffer == NULL) { + bpf_printk("failed to get alignment buffer"); + return NULL; + } + + // Copy size bytes from data to buffer + size = bound_number(size, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE); + long success = bpf_probe_read(buffer, size, data); + if (success != 0) { + bpf_printk("failed to copy data to alignment buffer"); + return NULL; + } + + data = buffer; + } + u64 start = get_area_start(); u64 end = get_area_end(start); if (end - start < size) @@ -109,9 +144,9 @@ static __always_inline void *write_target_data(void *data, s32 size) u64 updated_start = start + size; // align updated_start to 8 bytes - if (updated_start % 8 != 0) { - updated_start += 8 - (updated_start % 8); - } + // if (updated_start % 8 != 0) { + // updated_start += 8 - (updated_start % 8); + // } bpf_map_update_elem(&alloc_map, &start_index, &updated_start, BPF_ANY); bpf_printk("wrote %d bytes to userspace at addr: %lx", size, target); From 6527023ea3d45f7d7bbc2504fa983072d9dbf441 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 4 Oct 2023 16:17:13 +0300 Subject: [PATCH 25/67] test no slice append --- .../instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 132c25fd1..a66be2e14 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -176,7 +176,7 @@ int uprobe_LoopyWriter_HeaderHandler(struct pt_regs *ctx) struct hpack_header_field hf = {}; hf.name = key_str; hf.value = val_str; - append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); + // append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); return 0; } From a87add1e61bf8745e54f0655546de394b0cbf698 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 4 Oct 2023 21:56:13 +0300 Subject: [PATCH 26/67] debugging --- .../pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index a66be2e14..25ffcecc4 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -176,6 +176,7 @@ int uprobe_LoopyWriter_HeaderHandler(struct pt_regs *ctx) struct hpack_header_field hf = {}; hf.name = key_str; hf.value = val_str; + bpf_printk("item size %d", sizeof(hf)); // append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); return 0; } From ad6d428ea72bbf583ac6f58965219f04bde2ae5e Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 08:51:24 +0300 Subject: [PATCH 27/67] more testing --- internal/include/go_types.h | 15 +++++++++++++++ .../bpf/google.golang.org/grpc/bpf/probe.bpf.c | 8 ++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/internal/include/go_types.h b/internal/include/go_types.h index 35a37ae09..900343044 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -132,14 +132,29 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n // Update array slice->array = new_array; long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array)); + if (success != 0) + { + bpf_printk("append_item_to_slice: failed to update array pointer in userspace"); + return; + } // Update cap slice->cap++; success = bpf_probe_write_user(slice_user_ptr->cap, &slice->cap, sizeof(slice->cap)); + if (success != 0) + { + bpf_printk("append_item_to_slice: failed to update cap in userspace"); + return; + } } // Update len slice->len++; long success = bpf_probe_write_user(slice_user_ptr->len, &slice->len, sizeof(slice->len)); + if (success != 0) + { + bpf_printk("append_item_to_slice: failed to update len in userspace"); + return; + } } #endif \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 25ffcecc4..e700bf3e3 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -165,7 +165,7 @@ int uprobe_LoopyWriter_HeaderHandler(struct pt_regs *ctx) char tp_key[11] = "traceparent"; struct go_string key_str = write_user_go_string(tp_key, sizeof(tp_key)); if (key_str.len == 0) { - bpf_printk("write failed, aborting ebpf probe"); + bpf_printk("key write failed, aborting ebpf probe"); return 0; } @@ -173,11 +173,15 @@ int uprobe_LoopyWriter_HeaderHandler(struct pt_regs *ctx) char val[SPAN_CONTEXT_STRING_SIZE]; span_context_to_w3c_string(¤t_span_context, val); struct go_string val_str = write_user_go_string(val, sizeof(val)); + if (val_str.len == 0) { + bpf_printk("val write failed, aborting ebpf probe"); + return 0; + } struct hpack_header_field hf = {}; hf.name = key_str; hf.value = val_str; bpf_printk("item size %d", sizeof(hf)); - // append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); + append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); return 0; } From 38747811d63f061ff67c6771c4b837f2d420a873 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 12:06:59 +0300 Subject: [PATCH 28/67] ... --- .../bpf/net/http/server/bpf/probe.bpf.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 7a70bddca..c97a89eca 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -171,12 +171,19 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi SEC("uprobe/ServerMux_ServeHTTP") int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) { + // Get key u64 request_pos = 4; - // Get request struct void *req_ptr = get_argument(ctx, request_pos); void *req_ctx_ptr = 0; void *ctx_address = get_go_interface_instance(req_ptr + ctx_ptr_pos); bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), ctx_address); + void *key = get_consistent_key(ctx, ctx_address); + void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); + if (httpReq_ptr != NULL) + { + bpf_printk("httpReq_ptr is not null"); + return 0; + } struct http_request_t httpReq = {}; httpReq.start_time = bpf_ktime_get_ns(); @@ -215,9 +222,6 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) httpReq.sc = generate_span_context(); } - // Get key - void *key = get_consistent_key(ctx, ctx_address); - // Write event bpf_map_update_elem(&http_events, &key, &httpReq, 0); start_tracking_span(req_ctx_ptr, &httpReq.sc); From d856c1f153bb432f8d577f7b03c3cbbb9eaf9fb6 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 13:59:44 +0300 Subject: [PATCH 29/67] test append to slice --- internal/include/go_types.h | 104 ++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/internal/include/go_types.h b/internal/include/go_types.h index 900343044..5883dec4d 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -89,63 +89,65 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n { if (slice->len < slice->cap) { + bpf_printk("room in slice ! len %d cap %d", slice->len, slice->cap); // Room available on current array bpf_probe_write_user(slice->array + (item_size * slice->len), new_item, item_size); } else { + bpf_printk("no room in slice ! len %d cap %d", slice->len, slice->cap); // No room on current array - copy to new one of size item_size * (len + 1) - if (slice->len > MAX_DATA_SIZE || slice->len < 1) - { - return; - } - - s32 alloc_size = item_size * slice->len; - s32 bounded_alloc_size = alloc_size > MAX_REALLOCATION ? MAX_REALLOCATION : (alloc_size < 1 ? 1 : alloc_size); - - // Get buffer - s32 index = 0; - void *map_buff = bpf_map_lookup_elem(buff, &index); - if (!map_buff) - { - return; - } - - // Append to buffer - bpf_probe_read_user(map_buff, bounded_alloc_size, slice->array); - bpf_probe_read(map_buff + bounded_alloc_size, item_size, new_item); - - // Copy buffer to userspace - u32 new_array_size = bounded_alloc_size + item_size; - if (new_array_size > MAX_DATA_SIZE || new_array_size < 1) - { - return; - } - - void *new_array = write_target_data(map_buff, new_array_size); - if (new_array == NULL) - { - bpf_printk("append_item_to_slice: failed to copy new array to userspace"); - return; - } - - // Update array - slice->array = new_array; - long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array)); - if (success != 0) - { - bpf_printk("append_item_to_slice: failed to update array pointer in userspace"); - return; - } - - // Update cap - slice->cap++; - success = bpf_probe_write_user(slice_user_ptr->cap, &slice->cap, sizeof(slice->cap)); - if (success != 0) - { - bpf_printk("append_item_to_slice: failed to update cap in userspace"); - return; - } + // if (slice->len > MAX_DATA_SIZE || slice->len < 1) + // { + // return; + // } + + // s32 alloc_size = item_size * slice->len; + // s32 bounded_alloc_size = alloc_size > MAX_REALLOCATION ? MAX_REALLOCATION : (alloc_size < 1 ? 1 : alloc_size); + + // // Get buffer + // s32 index = 0; + // void *map_buff = bpf_map_lookup_elem(buff, &index); + // if (!map_buff) + // { + // return; + // } + + // // Append to buffer + // bpf_probe_read_user(map_buff, bounded_alloc_size, slice->array); + // bpf_probe_read(map_buff + bounded_alloc_size, item_size, new_item); + + // // Copy buffer to userspace + // u32 new_array_size = bounded_alloc_size + item_size; + // if (new_array_size > MAX_DATA_SIZE || new_array_size < 1) + // { + // return; + // } + + // void *new_array = write_target_data(map_buff, new_array_size); + // if (new_array == NULL) + // { + // bpf_printk("append_item_to_slice: failed to copy new array to userspace"); + // return; + // } + + // // Update array + // slice->array = new_array; + // long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array)); + // if (success != 0) + // { + // bpf_printk("append_item_to_slice: failed to update array pointer in userspace"); + // return; + // } + + // // Update cap + // slice->cap++; + // success = bpf_probe_write_user(slice_user_ptr->cap, &slice->cap, sizeof(slice->cap)); + // if (success != 0) + // { + // bpf_printk("append_item_to_slice: failed to update cap in userspace"); + // return; + // } } // Update len From 2d8fb1e7bc95faca6f304a1b4c50891e65613f04 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 15:36:03 +0300 Subject: [PATCH 30/67] Add validation in inject header for http instrumentation --- .../instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index c4fbe935a..6acb88b24 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -73,6 +73,10 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context if (curr_keyvalue_count == 0) { // No key-value pairs in the Go map, need to "allocate" memory for the user bucket_ptr = write_target_data(bucket_map_value, sizeof(struct map_bucket)); + if (bucket_ptr == NULL) { + bpf_printk("inject_header: Failed to write bucket to user"); + return -1; + } // Update the buckets pointer in the hmap struct to point to newly allocated bucket res = bpf_probe_write_user(buckets_ptr_ptr, &bucket_ptr, sizeof(bucket_ptr)); if (res < 0) { @@ -95,6 +99,10 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context // Prepare the key string for the user char key[W3C_KEY_LENGTH] = "traceparent"; void *ptr = write_target_data(key, W3C_KEY_LENGTH); + if (ptr == NULL) { + bpf_printk("inject_header: Failed to write key to user"); + return -1; + } bucket_map_value->keys[bucket_index] = (struct go_string) {.len = W3C_KEY_LENGTH, .str = ptr}; // Prepare the value string slice @@ -103,6 +111,7 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context span_context_to_w3c_string(propagated_ctx, val); ptr = write_target_data(val, sizeof(val)); if(ptr == NULL) { + bpf_printk("inject_header: Failed to write value to user"); return -1; } @@ -110,6 +119,7 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context struct go_string header_value = {.len = W3C_VAL_LENGTH, .str = ptr}; ptr = write_target_data((void*)&header_value, sizeof(header_value)); if(ptr == NULL) { + bpf_printk("inject_header: Failed to write go_string to user"); return -1; } From 8d0d8d7a989cd88014afc24972673d58bef2e126 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 21:09:49 +0300 Subject: [PATCH 31/67] fix context --- internal/include/uprobe.h | 30 +++++++++---------- internal/include/utils.h | 13 ++++++++ .../bpf/database/sql/bpf/probe.bpf.c | 2 +- .../github.com/gin-gonic/gin/bpf/probe.bpf.c | 2 +- .../google.golang.org/grpc/bpf/probe.bpf.c | 4 ++- .../grpc/server/bpf/probe.bpf.c | 4 ++- .../bpf/net/http/client/bpf/probe.bpf.c | 4 ++- .../bpf/net/http/server/bpf/probe.bpf.c | 4 ++- 8 files changed, 42 insertions(+), 21 deletions(-) diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index 46eaf36f5..d9fc503e1 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -32,20 +32,20 @@ // 4. Submit the constructed event to the agent code using perf buffer events_map // 5. Delete the span from the uprobe_context_map // 6. Delete the span from the global active spans map -#define UPROBE_RETURN(name, event_type, ctx_struct_pos, ctx_struct_offset, uprobe_context_map, events_map) \ -SEC("uprobe/##name##") \ -int uprobe_##name##_Returns(struct pt_regs *ctx) { \ - void *req_ptr = get_argument(ctx, ctx_struct_pos); \ - void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_struct_offset)); \ - void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \ - event_type tmpReq = {}; \ - bpf_probe_read(&tmpReq, sizeof(tmpReq), req_ptr_map); \ - tmpReq.end_time = bpf_ktime_get_ns(); \ - bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ - bpf_map_delete_elem(&uprobe_context_map, &key); \ - bool isRoot = (tmpReq.psc.TraceID[0] == 0); \ - stop_tracking_span(&tmpReq.sc, isRoot); \ - return 0; \ -} +#define UPROBE_RETURN(name, event_type, ctx_struct_pos, ctx_struct_offset, uprobe_context_map, events_map, is_root) \ +SEC("uprobe/##name##") \ +int uprobe_##name##_Returns(struct pt_regs *ctx) { \ + void *req_ptr = get_argument(ctx, ctx_struct_pos); \ + void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_struct_offset)); \ + void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \ + event_type tmpReq = {}; \ + bpf_probe_read(&tmpReq, sizeof(tmpReq), req_ptr_map); \ + tmpReq.end_time = bpf_ktime_get_ns(); \ + bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ + bpf_map_delete_elem(&uprobe_context_map, &key); \ + bool is_local_root = (is_root || bpf_is_zero(&tmpReq.psc, sizeof(tmpReq.psc))); \ + stop_tracking_span(&tmpReq.sc, is_local_root); \ + return 0; \ +} #endif \ No newline at end of file diff --git a/internal/include/utils.h b/internal/include/utils.h index fe70ee30d..033acc79f 100644 --- a/internal/include/utils.h +++ b/internal/include/utils.h @@ -83,3 +83,16 @@ static __always_inline void bpf_memset(unsigned char *dst, u32 size, unsigned ch dst[i] = value; } } + +static __always_inline bool bpf_is_zero(unsigned char *buff, u32 size) +{ + for (int i = 0; i < size; i++) + { + if (buff[i] != 0) + { + return false; + } + } + + return true; +} diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c index bff811f20..2bd1074e6 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c @@ -86,4 +86,4 @@ int uprobe_queryDC(struct pt_regs *ctx) { // This instrumentation attaches uprobe to the following function: // func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) -UPROBE_RETURN(queryDC, struct sql_request_t, 3, 0, sql_events, events) \ No newline at end of file +UPROBE_RETURN(queryDC, struct sql_request_t, 3, 0, sql_events, events, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index ade6c43ca..d30e707f9 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -89,4 +89,4 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { return 0; } -UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events) \ No newline at end of file +UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index e700bf3e3..5341a0577 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -123,6 +123,8 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); + bpf_memset(grpcReq.psc.TraceID, 0, TRACE_ID_SIZE); + bpf_memset(grpcReq.psc.SpanID, 0, SPAN_ID_SIZE); } // Get key @@ -134,7 +136,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, 3, 0, grpc_events, events) +UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, 3, 0, grpc_events, events, false) // func (l *loopyWriter) headerHandler(h *headerFrame) error SEC("uprobe/loopyWriter_headerHandler") diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 274c5de3a..47f79f751 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -91,6 +91,8 @@ int uprobe_server_handleStream(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); + bpf_memset(grpcReq.psc.TraceID, 0, TRACE_ID_SIZE); + bpf_memset(grpcReq.psc.SpanID, 0, SPAN_ID_SIZE); } // Set attributes @@ -114,7 +116,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(server_handleStream, struct grpc_request_t, 4, stream_ctx_pos, grpc_events, events) +UPROBE_RETURN(server_handleStream, struct grpc_request_t, 4, stream_ctx_pos, grpc_events, events, true) // func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error SEC("uprobe/decodeState_decodeHeader") diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 6acb88b24..0eeb6f554 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -166,6 +166,8 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); } else { httpReq.sc = generate_span_context(); + bpf_memset(httpReq.psc.TraceID, 0, TRACE_ID_SIZE); + bpf_memset(httpReq.psc.SpanID, 0, SPAN_ID_SIZE); } void *method_ptr = 0; @@ -209,4 +211,4 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // This instrumentation attaches uretprobe to the following function: // func net/http/client.Do(req *Request) -UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events) \ No newline at end of file +UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index c97a89eca..5978b5e8e 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -220,6 +220,8 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) else { httpReq.sc = generate_span_context(); + bpf_memset(httpReq.psc.TraceID, 0, TRACE_ID_SIZE); + bpf_memset(httpReq.psc.SpanID, 0, SPAN_ID_SIZE); } // Write event @@ -228,4 +230,4 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ServerMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events) \ No newline at end of file +UPROBE_RETURN(ServerMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true) \ No newline at end of file From a156b4f1bc4e6003bd971bf61521eb00800123bf Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 21:28:30 +0300 Subject: [PATCH 32/67] http client is root? --- internal/include/go_types.h | 105 +++++++++--------- .../bpf/net/http/client/bpf/probe.bpf.c | 2 +- 2 files changed, 53 insertions(+), 54 deletions(-) diff --git a/internal/include/go_types.h b/internal/include/go_types.h index 5883dec4d..505ad97d9 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -95,59 +95,58 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n } else { - bpf_printk("no room in slice ! len %d cap %d", slice->len, slice->cap); - // No room on current array - copy to new one of size item_size * (len + 1) - // if (slice->len > MAX_DATA_SIZE || slice->len < 1) - // { - // return; - // } - - // s32 alloc_size = item_size * slice->len; - // s32 bounded_alloc_size = alloc_size > MAX_REALLOCATION ? MAX_REALLOCATION : (alloc_size < 1 ? 1 : alloc_size); - - // // Get buffer - // s32 index = 0; - // void *map_buff = bpf_map_lookup_elem(buff, &index); - // if (!map_buff) - // { - // return; - // } - - // // Append to buffer - // bpf_probe_read_user(map_buff, bounded_alloc_size, slice->array); - // bpf_probe_read(map_buff + bounded_alloc_size, item_size, new_item); - - // // Copy buffer to userspace - // u32 new_array_size = bounded_alloc_size + item_size; - // if (new_array_size > MAX_DATA_SIZE || new_array_size < 1) - // { - // return; - // } - - // void *new_array = write_target_data(map_buff, new_array_size); - // if (new_array == NULL) - // { - // bpf_printk("append_item_to_slice: failed to copy new array to userspace"); - // return; - // } - - // // Update array - // slice->array = new_array; - // long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array)); - // if (success != 0) - // { - // bpf_printk("append_item_to_slice: failed to update array pointer in userspace"); - // return; - // } - - // // Update cap - // slice->cap++; - // success = bpf_probe_write_user(slice_user_ptr->cap, &slice->cap, sizeof(slice->cap)); - // if (success != 0) - // { - // bpf_printk("append_item_to_slice: failed to update cap in userspace"); - // return; - // } + //No room on current array - copy to new one of size item_size * (len + 1) + if (slice->len > MAX_DATA_SIZE || slice->len < 1) + { + return; + } + + s32 alloc_size = item_size * slice->len; + s32 bounded_alloc_size = alloc_size > MAX_REALLOCATION ? MAX_REALLOCATION : (alloc_size < 1 ? 1 : alloc_size); + + // Get buffer + s32 index = 0; + void *map_buff = bpf_map_lookup_elem(buff, &index); + if (!map_buff) + { + return; + } + + // Append to buffer + bpf_probe_read_user(map_buff, bounded_alloc_size, slice->array); + bpf_probe_read(map_buff + bounded_alloc_size, item_size, new_item); + + // Copy buffer to userspace + u32 new_array_size = bounded_alloc_size + item_size; + if (new_array_size > MAX_DATA_SIZE || new_array_size < 1) + { + return; + } + + void *new_array = write_target_data(map_buff, new_array_size); + if (new_array == NULL) + { + bpf_printk("append_item_to_slice: failed to copy new array to userspace"); + return; + } + + // Update array + slice->array = new_array; + long success = bpf_probe_write_user(slice_user_ptr->array, &slice->array, sizeof(slice->array)); + if (success != 0) + { + bpf_printk("append_item_to_slice: failed to update array pointer in userspace"); + return; + } + + // Update cap + slice->cap++; + success = bpf_probe_write_user(slice_user_ptr->cap, &slice->cap, sizeof(slice->cap)); + if (success != 0) + { + bpf_printk("append_item_to_slice: failed to update cap in userspace"); + return; + } } // Update len diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 0eeb6f554..a8a8d97dc 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -211,4 +211,4 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // This instrumentation attaches uretprobe to the following function: // func net/http/client.Do(req *Request) -UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events, false) \ No newline at end of file +UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events, true) \ No newline at end of file From 8efd894599f7803d1553ecf9145ade64387e5f51 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 21:59:23 +0300 Subject: [PATCH 33/67] ... --- internal/include/go_context.h | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 8b8dc0165..6b09d2d03 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -41,6 +41,11 @@ static __always_inline void *get_parent_go_context(void *ctx, void *map) { void *data = ctx; for (int i = 0; i < MAX_DISTANCE; i++) { + if (data == NULL) + { + break; + } + void *found_in_map = bpf_map_lookup_elem(map, &data); if (found_in_map != NULL) { @@ -72,9 +77,21 @@ static __always_inline struct span_context *get_parent_span_context(void *ctx) { return parent_sc; } -static __always_inline void start_tracking_span(void *ctx, struct span_context *sc) { - bpf_map_update_elem(&tracked_spans, &ctx, sc, BPF_ANY); - bpf_map_update_elem(&tracked_spans_by_sc, sc, &ctx, BPF_ANY); +static __always_inline void start_tracking_span(void *contextContext, struct span_context *sc) { + long err = 0; + err = bpf_map_update_elem(&tracked_spans, &contextContext, sc, BPF_ANY); + if (err != 0) + { + bpf_printk("Failed to update tracked_spans map: %ld", err); + return; + } + + err = bpf_map_update_elem(&tracked_spans_by_sc, sc, &contextContext, BPF_ANY); + if (err != 0) + { + bpf_printk("Failed to update tracked_spans_by_sc map: %ld", err); + return; + } } static __always_inline void stop_tracking_span(struct span_context *sc, bool isRoot) { From f6b26747a734f472402967c2393770925f427160 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 22:16:56 +0300 Subject: [PATCH 34/67] ... --- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 47f79f751..235b93dba 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -106,9 +106,10 @@ int uprobe_server_handleStream(struct pt_regs *ctx) bpf_probe_read(&grpcReq.method, method_size, method_ptr); // Get key + void *ctx_address = get_go_interface_instance(stream_ptr + stream_ctx_pos); void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(stream_ptr + stream_ctx_pos)); - void *key = get_consistent_key(ctx, (void *)(stream_ptr + stream_ctx_pos)); + bpf_probe_read(&ctx_iface, sizeof(ctx_iface), ctx_address); + void *key = get_consistent_key(ctx, ctx_address); // Write event bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); From 3f256fb8967ca00606707d3efebc281d3e0f1a5d Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Thu, 5 Oct 2023 23:41:55 +0300 Subject: [PATCH 35/67] ... --- internal/include/uprobe.h | 2 +- .../instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 1 - .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 1 - internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 1 - internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 1 - 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index d9fc503e1..bd2a4b674 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -43,7 +43,7 @@ int uprobe_##name##_Returns(struct pt_regs *ctx) { tmpReq.end_time = bpf_ktime_get_ns(); \ bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ bpf_map_delete_elem(&uprobe_context_map, &key); \ - bool is_local_root = (is_root || bpf_is_zero(&tmpReq.psc, sizeof(tmpReq.psc))); \ + bool is_local_root = (is_root || bpf_is_zero(&tmpReq.psc.SpanID, sizeof(tmpReq.psc.SpanID))); \ stop_tracking_span(&tmpReq.sc, is_local_root); \ return 0; \ } diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 5341a0577..f3c8a91db 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -123,7 +123,6 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); - bpf_memset(grpcReq.psc.TraceID, 0, TRACE_ID_SIZE); bpf_memset(grpcReq.psc.SpanID, 0, SPAN_ID_SIZE); } diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 235b93dba..2c783a2cd 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -91,7 +91,6 @@ int uprobe_server_handleStream(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); - bpf_memset(grpcReq.psc.TraceID, 0, TRACE_ID_SIZE); bpf_memset(grpcReq.psc.SpanID, 0, SPAN_ID_SIZE); } diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index a8a8d97dc..dbd975c6c 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -166,7 +166,6 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); } else { httpReq.sc = generate_span_context(); - bpf_memset(httpReq.psc.TraceID, 0, TRACE_ID_SIZE); bpf_memset(httpReq.psc.SpanID, 0, SPAN_ID_SIZE); } diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 5978b5e8e..f506b8163 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -220,7 +220,6 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) else { httpReq.sc = generate_span_context(); - bpf_memset(httpReq.psc.TraceID, 0, TRACE_ID_SIZE); bpf_memset(httpReq.psc.SpanID, 0, SPAN_ID_SIZE); } From 980e9e9da3aa603fd9141a214080f1e4cba6e199 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 00:02:12 +0300 Subject: [PATCH 36/67] ........ --- internal/include/uprobe.h | 2 +- .../instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 2 +- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 2 +- internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 2 +- internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index bd2a4b674..91a4db3bf 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -43,7 +43,7 @@ int uprobe_##name##_Returns(struct pt_regs *ctx) { tmpReq.end_time = bpf_ktime_get_ns(); \ bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ bpf_map_delete_elem(&uprobe_context_map, &key); \ - bool is_local_root = (is_root || bpf_is_zero(&tmpReq.psc.SpanID, sizeof(tmpReq.psc.SpanID))); \ + bool is_local_root = (is_root || bpf_is_zero(tmpReq.psc.SpanID, sizeof(tmpReq.psc.SpanID))); \ stop_tracking_span(&tmpReq.sc, is_local_root); \ return 0; \ } diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index f3c8a91db..8f7b580b5 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -123,7 +123,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); - bpf_memset(grpcReq.psc.SpanID, 0, SPAN_ID_SIZE); + bpf_memset(grpcReq.psc.SpanID, SPAN_ID_SIZE, 0); } // Get key diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 2c783a2cd..9edb7e039 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -91,7 +91,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); - bpf_memset(grpcReq.psc.SpanID, 0, SPAN_ID_SIZE); + bpf_memset(grpcReq.psc.SpanID, SPAN_ID_SIZE, 0); } // Set attributes diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index dbd975c6c..7d29e03e3 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -166,7 +166,7 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); } else { httpReq.sc = generate_span_context(); - bpf_memset(httpReq.psc.SpanID, 0, SPAN_ID_SIZE); + bpf_memset(httpReq.psc.SpanID, SPAN_ID_SIZE, 0); } void *method_ptr = 0; diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index f506b8163..9795e8a1e 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -220,7 +220,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) else { httpReq.sc = generate_span_context(); - bpf_memset(httpReq.psc.SpanID, 0, SPAN_ID_SIZE); + bpf_memset(httpReq.psc.SpanID, SPAN_ID_SIZE, 0); } // Write event From b70efbb876ef03f2b0e68c61cf920f97c0d5de7c Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 00:18:42 +0300 Subject: [PATCH 37/67] fff --- .../pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 1 - .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 1 - internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 1 - internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 1 - 4 files changed, 4 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 8f7b580b5..958270e41 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -123,7 +123,6 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); - bpf_memset(grpcReq.psc.SpanID, SPAN_ID_SIZE, 0); } // Get key diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 9edb7e039..c216604a3 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -91,7 +91,6 @@ int uprobe_server_handleStream(struct pt_regs *ctx) else { grpcReq.sc = generate_span_context(); - bpf_memset(grpcReq.psc.SpanID, SPAN_ID_SIZE, 0); } // Set attributes diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 7d29e03e3..dc6c95658 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -166,7 +166,6 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { generate_random_bytes(httpReq.sc.SpanID, SPAN_ID_SIZE); } else { httpReq.sc = generate_span_context(); - bpf_memset(httpReq.psc.SpanID, SPAN_ID_SIZE, 0); } void *method_ptr = 0; diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 9795e8a1e..865aae894 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -220,7 +220,6 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) else { httpReq.sc = generate_span_context(); - bpf_memset(httpReq.psc.SpanID, SPAN_ID_SIZE, 0); } // Write event From 519b6ca963a8a356e8ab0a4e5655da245041a9f0 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 10:13:07 +0300 Subject: [PATCH 38/67] use get_go_interface_instance --- internal/include/uprobe.h | 5 +++-- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 1 + .../pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index 91a4db3bf..9077b4fba 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -36,14 +36,15 @@ SEC("uprobe/##name##") \ int uprobe_##name##_Returns(struct pt_regs *ctx) { \ void *req_ptr = get_argument(ctx, ctx_struct_pos); \ - void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_struct_offset)); \ + void *ctx_address = get_go_interface_instance(req_ptr + ctx_struct_offset); \ + void *key = get_consistent_key(ctx, ctx_address); \ void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \ event_type tmpReq = {}; \ bpf_probe_read(&tmpReq, sizeof(tmpReq), req_ptr_map); \ tmpReq.end_time = bpf_ktime_get_ns(); \ bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ bpf_map_delete_elem(&uprobe_context_map, &key); \ - bool is_local_root = (is_root || bpf_is_zero(tmpReq.psc.SpanID, sizeof(tmpReq.psc.SpanID))); \ + bool is_local_root = (is_root || bpf_is_zero(tmpReq.psc.SpanID, sizeof(tmpReq.psc.SpanID))); \ stop_tracking_span(&tmpReq.sc, is_local_root); \ return 0; \ } diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index c216604a3..a8dd1a370 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -140,6 +140,7 @@ int uprobe_decodeState_decodeHeader(struct pt_regs *ctx) bpf_probe_read(current_key, sizeof(current_key), hf.name.str); if (bpf_memcmp(key, current_key, sizeof(key))) { + bpf_printk("Found traceparent header grpc"); char val[W3C_VAL_LENGTH]; bpf_probe_read(val, W3C_VAL_LENGTH, hf.value.str); diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 865aae894..7cec3a817 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -137,6 +137,7 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi { continue; } + bpf_printk("found traceparent header in http server"); void *traceparent_header_value_ptr = map_value->values[i].array; struct go_string traceparent_header_value_go_str; res = bpf_probe_read(&traceparent_header_value_go_str, sizeof(traceparent_header_value_go_str), traceparent_header_value_ptr); From a80aa637eb1c0ac67e40065543a729b56713e6b2 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 10:17:44 +0300 Subject: [PATCH 39/67] include go types in uprobe.h --- .vscode/settings.json | 5 +++++ internal/include/uprobe.h | 1 + 2 files changed, 6 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..e15cc4010 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "go_types.h": "c" + } +} \ No newline at end of file diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index 9077b4fba..b7a9d4c9c 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -18,6 +18,7 @@ #include "common.h" #include "span_context.h" #include "go_context.h" +#include "go_types.h" #define BASE_SPAN_PROPERTIES \ u64 start_time; \ From b79b6410d64436a48885178b1ef48a1c9bc3643c Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 11:27:26 +0300 Subject: [PATCH 40/67] more context propagation --- internal/include/go_context.h | 8 ++++++++ internal/include/uprobe.h | 5 ++--- .../pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c | 2 +- .../bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c | 2 +- .../bpf/google.golang.org/grpc/bpf/probe.bpf.c | 2 +- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 2 +- .../pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 5 +++-- .../pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 2 +- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 6b09d2d03..3ef295da1 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -108,4 +108,12 @@ static __always_inline void stop_tracking_span(struct span_context *sc, bool isR bpf_map_delete_elem(&tracked_spans_by_sc, sc); } +static __always_inline void *get_Go_context(void *ctx, int context_pos, u64 context_offset, bool passed_as_arg) { + void *arg = get_argument(ctx, context_pos); + if (passed_as_arg) { + return arg; + } + return get_go_interface_instance(arg + context_offset); +} + #endif \ No newline at end of file diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index b7a9d4c9c..0105e18e6 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -33,11 +33,10 @@ // 4. Submit the constructed event to the agent code using perf buffer events_map // 5. Delete the span from the uprobe_context_map // 6. Delete the span from the global active spans map -#define UPROBE_RETURN(name, event_type, ctx_struct_pos, ctx_struct_offset, uprobe_context_map, events_map, is_root) \ +#define UPROBE_RETURN(name, event_type, ctx_struct_pos, ctx_struct_offset, uprobe_context_map, events_map, is_root, context_is_arg) \ SEC("uprobe/##name##") \ int uprobe_##name##_Returns(struct pt_regs *ctx) { \ - void *req_ptr = get_argument(ctx, ctx_struct_pos); \ - void *ctx_address = get_go_interface_instance(req_ptr + ctx_struct_offset); \ + void *ctx_address = get_Go_context(ctx, ctx_struct_pos, ctx_struct_offset, context_is_arg); \ void *key = get_consistent_key(ctx, ctx_address); \ void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \ event_type tmpReq = {}; \ diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c index 2bd1074e6..744dc5057 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c @@ -86,4 +86,4 @@ int uprobe_queryDC(struct pt_regs *ctx) { // This instrumentation attaches uprobe to the following function: // func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) -UPROBE_RETURN(queryDC, struct sql_request_t, 3, 0, sql_events, events, false) \ No newline at end of file +UPROBE_RETURN(queryDC, struct sql_request_t, 3, 0, sql_events, events, false, true) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index d30e707f9..7b15a59d6 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -89,4 +89,4 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { return 0; } -UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true) \ No newline at end of file +UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 958270e41..9b1489606 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -134,7 +134,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, 3, 0, grpc_events, events, false) +UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, 3, 0, grpc_events, events, false, true) // func (l *loopyWriter) headerHandler(h *headerFrame) error SEC("uprobe/loopyWriter_headerHandler") diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index a8dd1a370..a2b297481 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -115,7 +115,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(server_handleStream, struct grpc_request_t, 4, stream_ctx_pos, grpc_events, events, true) +UPROBE_RETURN(server_handleStream, struct grpc_request_t, 4, stream_ctx_pos, grpc_events, events, true, false) // func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error SEC("uprobe/decodeState_decodeHeader") diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index dc6c95658..e324f8b91 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -156,7 +156,8 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { void *req_ptr = get_argument(ctx, request_pos); // Get parent if exists - void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); + void *context_ptr = get_go_interface_instance(req_ptr+ctx_ptr_pos); + //void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); void *context_ptr_val = 0; bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); @@ -209,4 +210,4 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // This instrumentation attaches uretprobe to the following function: // func net/http/client.Do(req *Request) -UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events, true) \ No newline at end of file +UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events, true, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 7cec3a817..7424a5fb3 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -229,4 +229,4 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ServerMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true) \ No newline at end of file +UPROBE_RETURN(ServerMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true, false) \ No newline at end of file From 43053de68b23c124f5699484e732d25b9cb312ed Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 11:32:15 +0300 Subject: [PATCH 41/67] add include --- internal/include/go_context.h | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 3ef295da1..2eb9b2657 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -16,6 +16,7 @@ #define _GO_CONTEXT_H_ #include "bpf_helpers.h" +#include "go_types.h" #define MAX_DISTANCE 10 From 18a8f79260a53ccfea3b0fbe19a73a53fc152904 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 12:56:16 +0300 Subject: [PATCH 42/67] checking if http client uprobe context was created --- .../instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index e324f8b91..66d7470b7 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -157,6 +157,13 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // Get parent if exists void *context_ptr = get_go_interface_instance(req_ptr+ctx_ptr_pos); + void *key = get_consistent_key(ctx, context_ptr); + void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); + if (httpReq_ptr != NULL) + { + bpf_printk("client: httpReq_ptr is not null"); + return 0; + } //void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); void *context_ptr_val = 0; bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); @@ -200,7 +207,7 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { } // Get key - void *key = get_consistent_key(ctx, context_ptr); + // void *key = get_consistent_key(ctx, context_ptr); // Write event bpf_map_update_elem(&http_events, &key, &httpReq, 0); From 41bed4c889af54a54df41906532cbfa3c05ed949 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 13:55:34 +0300 Subject: [PATCH 43/67] align get_consistent_key --- .vscode/settings.json | 5 ----- internal/include/arguments.h | 4 +--- internal/include/go_context.h | 4 +++- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 2 +- .../pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 7 ++++--- .../pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 2 +- 6 files changed, 10 insertions(+), 14 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index e15cc4010..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files.associations": { - "go_types.h": "c" - } -} \ No newline at end of file diff --git a/internal/include/arguments.h b/internal/include/arguments.h index 70f42fc54..b5b2e30ee 100644 --- a/internal/include/arguments.h +++ b/internal/include/arguments.h @@ -80,9 +80,7 @@ static __always_inline void *get_consistent_key(struct pt_regs *ctx, void *conte return (void *)GOROUTINE(ctx); } - void *ctx_ptr = 0; - bpf_probe_read(&ctx_ptr, sizeof(ctx_ptr), contextContext); - return ctx_ptr; + return contextContext; } #endif \ No newline at end of file diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 2eb9b2657..79b52ce68 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -114,7 +114,9 @@ static __always_inline void *get_Go_context(void *ctx, int context_pos, u64 cont if (passed_as_arg) { return arg; } - return get_go_interface_instance(arg + context_offset); + void *ctx_addr = get_go_interface_instance(arg + context_offset); + void *ctx_val = 0; + bpf_probe_read_user(&ctx_val, sizeof(ctx_val), ctx_addr); } #endif \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index a2b297481..3a120af9c 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -107,7 +107,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) void *ctx_address = get_go_interface_instance(stream_ptr + stream_ctx_pos); void *ctx_iface = 0; bpf_probe_read(&ctx_iface, sizeof(ctx_iface), ctx_address); - void *key = get_consistent_key(ctx, ctx_address); + void *key = get_consistent_key(ctx, ctx_iface); // Write event bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 66d7470b7..cc6e33ce0 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -157,7 +157,9 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // Get parent if exists void *context_ptr = get_go_interface_instance(req_ptr+ctx_ptr_pos); - void *key = get_consistent_key(ctx, context_ptr); + void *context_ptr_val = 0; + bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + void *key = get_consistent_key(ctx, context_ptr_val); void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) { @@ -165,8 +167,7 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { return 0; } //void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); if (parent_span_ctx != NULL) { bpf_probe_read(&httpReq.psc, sizeof(httpReq.psc), parent_span_ctx); diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 7424a5fb3..3dfdf5d3d 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -178,7 +178,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) void *req_ctx_ptr = 0; void *ctx_address = get_go_interface_instance(req_ptr + ctx_ptr_pos); bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), ctx_address); - void *key = get_consistent_key(ctx, ctx_address); + void *key = get_consistent_key(ctx, req_ctx_ptr); void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) { From cd3ebe5538e3409f06a39c05360c7033c9e44c86 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 14:07:22 +0300 Subject: [PATCH 44/67] return ctx_val --- internal/include/go_context.h | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 79b52ce68..7513d8032 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -117,6 +117,7 @@ static __always_inline void *get_Go_context(void *ctx, int context_pos, u64 cont void *ctx_addr = get_go_interface_instance(arg + context_offset); void *ctx_val = 0; bpf_probe_read_user(&ctx_val, sizeof(ctx_val), ctx_addr); + return ctx_val; } #endif \ No newline at end of file From 9bcfc45687f9e6e5f57e0e328f6302fa42e0e48d Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 15:05:55 +0300 Subject: [PATCH 45/67] test mlock --- internal/pkg/process/analyze.go | 6 ++++++ internal/pkg/process/ptrace/ptrace_linux.go | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index 503dbdfa8..3dd9c486c 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -107,6 +107,12 @@ func (a *Analyzer) remoteMmap(pid int, mapSize uint64) (uint64, error) { return 0, err } + err = program.Mlock(addr, mapSize) + if err != nil { + log.Logger.Error(err, "Failed to mlock", "pid", pid) + return 0, err + } + return addr, nil } diff --git a/internal/pkg/process/ptrace/ptrace_linux.go b/internal/pkg/process/ptrace/ptrace_linux.go index 39c8cc27a..8aab16919 100644 --- a/internal/pkg/process/ptrace/ptrace_linux.go +++ b/internal/pkg/process/ptrace/ptrace_linux.go @@ -234,4 +234,10 @@ func (p *TracedProgram) Madvise(addr uint64, length uint64) error { _, err = p.Syscall(syscall.SYS_MADVISE, addr, length, advice, 0, 0, 0) return err +} + +// Mlock runs mlock syscall. +func (p *TracedProgram) Mlock(addr uint64, length uint64) error { + _, err := p.Syscall(syscall.SYS_MLOCK, addr, length, 0, 0, 0, 0) + return err } \ No newline at end of file From 9ed2a9bff63ed5156625174e36ab3305a9604db2 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Fri, 6 Oct 2023 15:31:36 +0300 Subject: [PATCH 46/67] more testing --- internal/include/alloc.h | 6 ++++++ internal/pkg/process/ptrace/ptrace_linux.go | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/include/alloc.h b/internal/include/alloc.h index 1b0e5a029..6c3490f58 100644 --- a/internal/include/alloc.h +++ b/internal/include/alloc.h @@ -137,6 +137,12 @@ static __always_inline void *write_target_data(void *data, s32 size) void *target = (void *)start; size = bound_number(size, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE); + u64 page_offset = (u64)target & 0xFFF; + u64 dist_to_next_page = 4096 - page_offset; + if (dist_to_next_page < size) + { + target += dist_to_next_page; + } long success = bpf_probe_write_user(target, data, size); if (success == 0) { diff --git a/internal/pkg/process/ptrace/ptrace_linux.go b/internal/pkg/process/ptrace/ptrace_linux.go index 8aab16919..27c4b9bef 100644 --- a/internal/pkg/process/ptrace/ptrace_linux.go +++ b/internal/pkg/process/ptrace/ptrace_linux.go @@ -238,6 +238,7 @@ func (p *TracedProgram) Madvise(addr uint64, length uint64) error { // Mlock runs mlock syscall. func (p *TracedProgram) Mlock(addr uint64, length uint64) error { - _, err := p.Syscall(syscall.SYS_MLOCK, addr, length, 0, 0, 0, 0) + ret, err := p.Syscall(syscall.SYS_MLOCK, addr, length, 0, 0, 0, 0) + log.Logger.V(0).Info("mlock ret", "ret", ret) return err } \ No newline at end of file From c842141bdda37fc50ba0ab0f858c33eb406127b1 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 7 Oct 2023 11:34:11 +0300 Subject: [PATCH 47/67] Test reducing the mmap size --- internal/pkg/process/analyze.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index 3dd9c486c..c6126eae3 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -140,7 +140,7 @@ func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*Targ result.GoVersion = goVersion result.Libraries = modules - mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 50) + mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 2) addr, err := a.remoteMmap(pid, mapSize) if err != nil { log.Logger.Error(err, "Failed to mmap") From 48d64149de5dd7fd9efe4a87f71f9e45c045c721 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 7 Oct 2023 13:30:14 +0300 Subject: [PATCH 48/67] Increase back the pages allocated --- internal/pkg/process/analyze.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index c6126eae3..3dd9c486c 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -140,7 +140,7 @@ func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*Targ result.GoVersion = goVersion result.Libraries = modules - mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 2) + mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 50) addr, err := a.remoteMmap(pid, mapSize) if err != nil { log.Logger.Error(err, "Failed to mmap") From a038935a91c2eadb36368cbdf6c6882dfb221f23 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 8 Oct 2023 10:28:38 +0300 Subject: [PATCH 49/67] refactor context prop --- internal/include/go_context.h | 26 ++++++++++++++++--- internal/include/uprobe.h | 4 +-- .../bpf/database/sql/bpf/probe.bpf.c | 14 ++++++---- .../bpf/database/sql/bpf_bpfel_arm64.go | 3 +++ .../bpf/database/sql/bpf_bpfel_x86.go | 3 +++ .../github.com/gin-gonic/gin/bpf/probe.bpf.c | 13 +++++++--- .../gin-gonic/gin/bpf_bpfel_arm64.go | 6 +++++ .../github.com/gin-gonic/gin/bpf_bpfel_x86.go | 6 +++++ .../google.golang.org/grpc/bpf/probe.bpf.c | 13 ++++++---- .../google.golang.org/grpc/bpf_bpfel_arm64.go | 3 +++ .../google.golang.org/grpc/bpf_bpfel_x86.go | 3 +++ .../grpc/server/bpf/probe.bpf.c | 12 ++++++--- .../grpc/server/bpf_bpfel_arm64.go | 3 +++ .../grpc/server/bpf_bpfel_x86.go | 3 +++ .../bpf/net/http/client/bpf/probe.bpf.c | 15 ++++++----- .../bpf/net/http/client/bpf_bpfel_arm64.go | 3 +++ .../bpf/net/http/client/bpf_bpfel_x86.go | 3 +++ .../bpf/net/http/server/bpf/probe.bpf.c | 18 ++++++++----- .../bpf/net/http/server/bpf_bpfel_arm64.go | 15 ++++++----- .../bpf/net/http/server/bpf_bpfel_x86.go | 15 ++++++----- .../bpf/net/http/server/probe.go | 4 +-- 21 files changed, 133 insertions(+), 52 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 7513d8032..ce0c45ff9 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -38,6 +38,24 @@ struct __uint(pinning, LIBBPF_PIN_BY_NAME); } tracked_spans_by_sc SEC(".maps"); +// Identifies the location of the context.Context in the function arguments +struct go_context_loc +{ + // The argument position of the context.Context data pointer + // In case the context.Context is passed as an argument, + // this is the argument index of the pointer (starting from 1). + // In case the context.Context is a member of a struct, + // this is the argument index of the struct pointer (starting from 1). + int context_pos; + // In case the context.Context is a member of a struct, + // this is the offset of the context.Context member in the struct. + const volatile u64 *context_offset_ptr; + // Indicates whether context.Context is passed as an argument or is a member of a struct + bool passed_as_arg; +}; + +typedef struct span_context* (*get_parent_fb)(void*); + static __always_inline void *get_parent_go_context(void *ctx, void *map) { void *data = ctx; for (int i = 0; i < MAX_DISTANCE; i++) @@ -109,12 +127,12 @@ static __always_inline void stop_tracking_span(struct span_context *sc, bool isR bpf_map_delete_elem(&tracked_spans_by_sc, sc); } -static __always_inline void *get_Go_context(void *ctx, int context_pos, u64 context_offset, bool passed_as_arg) { - void *arg = get_argument(ctx, context_pos); - if (passed_as_arg) { +static __always_inline void *get_Go_context(void *ctx, struct go_context_loc *loc) { + void *arg = get_argument(ctx, loc->context_pos); + if (loc->passed_as_arg) { return arg; } - void *ctx_addr = get_go_interface_instance(arg + context_offset); + void *ctx_addr = get_go_interface_instance(arg + (*loc->context_offset_ptr)); void *ctx_val = 0; bpf_probe_read_user(&ctx_val, sizeof(ctx_val), ctx_addr); return ctx_val; diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index 0105e18e6..fdb3fed5e 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -33,10 +33,10 @@ // 4. Submit the constructed event to the agent code using perf buffer events_map // 5. Delete the span from the uprobe_context_map // 6. Delete the span from the global active spans map -#define UPROBE_RETURN(name, event_type, ctx_struct_pos, ctx_struct_offset, uprobe_context_map, events_map, is_root, context_is_arg) \ +#define UPROBE_RETURN(name, event_type, ctx_loc_ptr, uprobe_context_map, events_map, is_root) \ SEC("uprobe/##name##") \ int uprobe_##name##_Returns(struct pt_regs *ctx) { \ - void *ctx_address = get_Go_context(ctx, ctx_struct_pos, ctx_struct_offset, context_is_arg); \ + void *ctx_address = get_Go_context(ctx, ctx_loc_ptr); \ void *key = get_consistent_key(ctx, ctx_address); \ void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \ event_type tmpReq = {}; \ diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c index 744dc5057..885cbddcc 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c @@ -42,6 +42,12 @@ struct { // Injected in init volatile const bool should_include_db_statement; +struct go_context_loc queryDC_ctx_loc = { + .context_pos = 3, + .passed_as_arg = true, + .context_offset_ptr = NULL, +}; + // This instrumentation attaches uprobe to the following function: // func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) SEC("uprobe/queryDC") @@ -63,9 +69,7 @@ int uprobe_queryDC(struct pt_regs *ctx) { } // Get parent if exists - void *context_ptr = get_argument(ctx, context_ptr_pos); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + void *context_ptr_val = get_Go_context(ctx, &queryDC_ctx_loc); struct span_context *span_ctx = get_parent_span_context(context_ptr_val); if (span_ctx != NULL) { // Set the parent context @@ -77,7 +81,7 @@ int uprobe_queryDC(struct pt_regs *ctx) { } // Get key - void *key = get_consistent_key(ctx, context_ptr); + void *key = get_consistent_key(ctx, context_ptr_val); bpf_map_update_elem(&sql_events, &key, &sql_request, 0); start_tracking_span(context_ptr_val, &sql_request.sc); @@ -86,4 +90,4 @@ int uprobe_queryDC(struct pt_regs *ctx) { // This instrumentation attaches uprobe to the following function: // func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) -UPROBE_RETURN(queryDC, struct sql_request_t, 3, 0, sql_events, events, false, true) \ No newline at end of file +UPROBE_RETURN(queryDC, struct sql_request_t, &queryDC_ctx_loc, sql_events, events, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go index 18fa1aa93..478622e4f 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go @@ -75,6 +75,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` SqlEvents *ebpf.MapSpec `ebpf:"sql_events"` @@ -101,6 +102,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` SqlEvents *ebpf.Map `ebpf:"sql_events"` @@ -110,6 +112,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.SqlEvents, diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go index 86185db34..9f250fc76 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go @@ -75,6 +75,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` SqlEvents *ebpf.MapSpec `ebpf:"sql_events"` @@ -101,6 +102,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` SqlEvents *ebpf.Map `ebpf:"sql_events"` @@ -110,6 +112,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.SqlEvents, diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index 7b15a59d6..46aaf9140 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -46,6 +46,12 @@ volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; volatile const u64 ctx_ptr_pos; +struct go_context_loc GinEngine_ServeHTTP_ctx_loc = { + .context_pos = 4, + .passed_as_arg = false, + .context_offset_ptr = &ctx_ptr_pos, +}; + // This instrumentation attaches uprobe to the following function: // func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) SEC("uprobe/GinEngine_ServeHTTP") @@ -56,6 +62,7 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { // Get request struct void *req_ptr = get_argument(ctx, request_pos); + void *req_ctx_ptr = get_Go_context(ctx, &GinEngine_ServeHTTP_ctx_loc); // Get method from request void *method_ptr = 0; @@ -78,9 +85,7 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { bpf_probe_read(&httpReq.path, path_size, path_ptr); // Get key - void *req_ctx_ptr = 0; - bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), (void *)(req_ptr + ctx_ptr_pos)); - void *key = get_consistent_key(ctx, (void *)(req_ptr + ctx_ptr_pos)); + void *key = get_consistent_key(ctx, req_ctx_ptr); // Write event httpReq.sc = generate_span_context(); @@ -89,4 +94,4 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { return 0; } -UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true, false) \ No newline at end of file +UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, &GinEngine_ServeHTTP_ctx_loc, http_events, events, true) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go index e2aaf959e..4164a79e8 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go @@ -76,6 +76,8 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` @@ -101,6 +103,8 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` HttpEvents *ebpf.Map `ebpf:"http_events"` TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` @@ -109,6 +113,8 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, + m.AllocMap, m.Events, m.HttpEvents, m.TrackedSpans, diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go index 40a92c783..9a15b0cb8 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go @@ -76,6 +76,8 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` TrackedSpans *ebpf.MapSpec `ebpf:"tracked_spans"` @@ -101,6 +103,8 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` + AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` HttpEvents *ebpf.Map `ebpf:"http_events"` TrackedSpans *ebpf.Map `ebpf:"tracked_spans"` @@ -109,6 +113,8 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, + m.AllocMap, m.Events, m.HttpEvents, m.TrackedSpans, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 9b1489606..e0c7e07d4 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -78,6 +78,12 @@ volatile const u64 httpclient_nextid_pos; volatile const u64 headerFrame_streamid_pos; volatile const u64 headerFrame_hf_pos; +struct go_context_loc ClientConn_Invoke_ctx_loc = { + .context_pos = 3, + .passed_as_arg = true, + .context_offset_ptr = NULL, +}; + // This instrumentation attaches uprobe to the following function: // func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error SEC("uprobe/ClientConn_Invoke") @@ -85,7 +91,6 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) { // positions u64 clientconn_pos = 1; - u64 context_pos = 3; u64 method_ptr_pos = 4; u64 method_len_pos = 5; @@ -110,9 +115,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) bpf_probe_read(&grpcReq.target, target_size, target_ptr); // Get parent if exists - void *context_ptr = get_argument(ctx, context_pos); - // void *context_ptr_val = 0; - // bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + void *context_ptr = get_Go_context(ctx, &ClientConn_Invoke_ctx_loc); struct span_context *parent_span_ctx = get_parent_span_context(context_ptr); if (parent_span_ctx != NULL) { @@ -134,7 +137,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, 3, 0, grpc_events, events, false, true) +UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, &ClientConn_Invoke_ctx_loc, grpc_events, events, false) // func (l *loopyWriter) headerHandler(h *headerFrame) error SEC("uprobe/loopyWriter_headerHandler") diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go index 489bb8978..5535c1ac6 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go @@ -80,6 +80,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -108,6 +109,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -119,6 +121,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go index f26a8e07e..c75a14d2f 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go @@ -80,6 +80,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -108,6 +109,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -119,6 +121,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 3a120af9c..b8fc70c80 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -68,6 +68,12 @@ volatile const u64 frame_stream_id_pod; volatile const u64 stream_id_pos; volatile const u64 stream_ctx_pos; +struct go_context_loc stream_ctx_loc = { + .context_pos = 4, + .passed_as_arg = false, + .context_offset_ptr = &stream_ctx_pos, +}; + // This instrumentation attaches uprobe to the following function: // func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { SEC("uprobe/server_handleStream") @@ -104,9 +110,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) bpf_probe_read(&grpcReq.method, method_size, method_ptr); // Get key - void *ctx_address = get_go_interface_instance(stream_ptr + stream_ctx_pos); - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), ctx_address); + void *ctx_iface = get_Go_context(ctx, &stream_ctx_loc); void *key = get_consistent_key(ctx, ctx_iface); // Write event @@ -115,7 +119,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(server_handleStream, struct grpc_request_t, 4, stream_ctx_pos, grpc_events, events, true, false) +UPROBE_RETURN(server_handleStream, struct grpc_request_t, &stream_ctx_loc, grpc_events, events, true) // func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error SEC("uprobe/decodeState_decodeHeader") diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go index 8002c33ab..120e170e2 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go @@ -76,6 +76,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -103,6 +104,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -113,6 +115,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go index db9a7611c..624ee586b 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go @@ -76,6 +76,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -103,6 +104,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -113,6 +115,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index cc6e33ce0..51bd14e8e 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -145,6 +145,12 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context return 0; } +struct go_context_loc HttpClient_ctx_loc = { + .context_pos = 2, + .passed_as_arg = false, + .context_offset_ptr = &ctx_ptr_pos, +}; + // This instrumentation attaches uprobe to the following function: // func net/http/client.Do(req *Request) SEC("uprobe/HttpClient_Do") @@ -156,9 +162,7 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { void *req_ptr = get_argument(ctx, request_pos); // Get parent if exists - void *context_ptr = get_go_interface_instance(req_ptr+ctx_ptr_pos); - void *context_ptr_val = 0; - bpf_probe_read(&context_ptr_val, sizeof(context_ptr_val), context_ptr); + void *context_ptr_val = get_Go_context(ctx, &HttpClient_ctx_loc); void *key = get_consistent_key(ctx, context_ptr_val); void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) @@ -207,9 +211,6 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { bpf_printk("uprobe_HttpClient_Do: Failed to inject header"); } - // Get key - // void *key = get_consistent_key(ctx, context_ptr); - // Write event bpf_map_update_elem(&http_events, &key, &httpReq, 0); start_tracking_span(context_ptr_val, &httpReq.sc); @@ -218,4 +219,4 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // This instrumentation attaches uretprobe to the following function: // func net/http/client.Do(req *Request) -UPROBE_RETURN(HttpClient_Do, struct http_request_t, 2, ctx_ptr_pos, http_events, events, true, false) \ No newline at end of file +UPROBE_RETURN(HttpClient_Do, struct http_request_t, &HttpClient_ctx_loc, http_events, events, true) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go index 6846ab481..197fba15a 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go @@ -76,6 +76,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -103,6 +104,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -113,6 +115,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go index 6352e91da..8f049cd61 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go @@ -76,6 +76,7 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -103,6 +104,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -113,6 +115,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 3dfdf5d3d..405f9596c 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -167,17 +167,21 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi return NULL; } +struct go_context_loc ServeHTTP_ctx_loc = { + .context_pos = 4, + .passed_as_arg = false, + .context_offset_ptr = &ctx_ptr_pos, +}; + // This instrumentation attaches uprobe to the following function: -// func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) -SEC("uprobe/ServerMux_ServeHTTP") -int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) +// func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) +SEC("uprobe/HandlerFunc_ServeHTTP") +int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) { // Get key u64 request_pos = 4; void *req_ptr = get_argument(ctx, request_pos); - void *req_ctx_ptr = 0; - void *ctx_address = get_go_interface_instance(req_ptr + ctx_ptr_pos); - bpf_probe_read(&req_ctx_ptr, sizeof(req_ctx_ptr), ctx_address); + void *req_ctx_ptr = get_Go_context(ctx, &ServeHTTP_ctx_loc); void *key = get_consistent_key(ctx, req_ctx_ptr); void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) @@ -229,4 +233,4 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ServerMux_ServeHTTP, struct http_request_t, 4, ctx_ptr_pos, http_events, events, true, false) \ No newline at end of file +UPROBE_RETURN(HandlerFunc_ServeHTTP, struct http_request_t, &ServeHTTP_ctx_loc, http_events, events, true) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go index 9ae25dca9..a62b33a43 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go @@ -68,14 +68,15 @@ type bpfSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfProgramSpecs struct { - UprobeServerMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` + UprobeHandlerFuncServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP"` + UprobeHandlerFuncServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` } // bpfMapSpecs contains maps before they are loaded into the kernel. // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -104,6 +105,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -115,6 +117,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, @@ -129,14 +132,14 @@ func (m *bpfMaps) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfPrograms struct { - UprobeServerMuxServeHTTP *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` + UprobeHandlerFuncServeHTTP *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP"` + UprobeHandlerFuncServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` } func (p *bpfPrograms) Close() error { return _BpfClose( - p.UprobeServerMuxServeHTTP, - p.UprobeServerMuxServeHTTP_Returns, + p.UprobeHandlerFuncServeHTTP, + p.UprobeHandlerFuncServeHTTP_Returns, ) } diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go index 1bb9e8c04..23d51ea5d 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go @@ -68,14 +68,15 @@ type bpfSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfProgramSpecs struct { - UprobeServerMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` + UprobeHandlerFuncServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP"` + UprobeHandlerFuncServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` } // bpfMapSpecs contains maps before they are loaded into the kernel. // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { + AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -104,6 +105,7 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { + AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -115,6 +117,7 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( + m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, @@ -129,14 +132,14 @@ func (m *bpfMaps) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfPrograms struct { - UprobeServerMuxServeHTTP *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` + UprobeHandlerFuncServeHTTP *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP"` + UprobeHandlerFuncServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_HandlerFunc_ServeHTTP_Returns"` } func (p *bpfPrograms) Close() error { return _BpfClose( - p.UprobeServerMuxServeHTTP, - p.UprobeServerMuxServeHTTP_Returns, + p.UprobeHandlerFuncServeHTTP, + p.UprobeHandlerFuncServeHTTP_Returns, ) } diff --git a/internal/pkg/instrumentors/bpf/net/http/server/probe.go b/internal/pkg/instrumentors/bpf/net/http/server/probe.go index 34fc4058e..6e9b53532 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/internal/pkg/instrumentors/bpf/net/http/server/probe.go @@ -152,7 +152,7 @@ func (h *Instrumentor) registerProbes(ctx *context.InstrumentorContext, funcName return } - up, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeServerMuxServeHTTP, &link.UprobeOptions{ + up, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeHandlerFuncServeHTTP, &link.UprobeOptions{ Address: offset, }) if err != nil { @@ -164,7 +164,7 @@ func (h *Instrumentor) registerProbes(ctx *context.InstrumentorContext, funcName h.uprobes = append(h.uprobes, up) for _, ret := range retOffsets { - retProbe, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeServerMuxServeHTTP_Returns, &link.UprobeOptions{ + retProbe, err := ctx.Executable.Uprobe("", h.bpfObjects.UprobeHandlerFuncServeHTTP_Returns, &link.UprobeOptions{ Address: ret, }) if err != nil { From 7cd9460be8da76867342d9269095e9ded32bcfae Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 8 Oct 2023 15:21:04 +0300 Subject: [PATCH 50/67] Add volataile const for global structs --- internal/include/arguments.h | 2 +- internal/include/go_context.h | 8 ++++++++ .../pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c | 2 +- .../bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c | 2 +- .../bpf/google.golang.org/grpc/bpf/probe.bpf.c | 2 +- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 2 +- .../instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 2 +- .../instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 10 +++++++++- 8 files changed, 23 insertions(+), 7 deletions(-) diff --git a/internal/include/arguments.h b/internal/include/arguments.h index b5b2e30ee..e93676e20 100644 --- a/internal/include/arguments.h +++ b/internal/include/arguments.h @@ -57,7 +57,7 @@ void *get_argument_by_stack(struct pt_regs *ctx, int index) return ptr; } -void *get_argument(struct pt_regs *ctx, int index) +void __always_inline *get_argument(struct pt_regs *ctx, int index) { if (is_registers_abi) { diff --git a/internal/include/go_context.h b/internal/include/go_context.h index ce0c45ff9..2c607b8d9 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -128,10 +128,18 @@ static __always_inline void stop_tracking_span(struct span_context *sc, bool isR } static __always_inline void *get_Go_context(void *ctx, struct go_context_loc *loc) { + if (loc == NULL) { + bpf_printk("go_context_loc is null"); + return NULL; + } void *arg = get_argument(ctx, loc->context_pos); if (loc->passed_as_arg) { return arg; } + if (loc->context_offset_ptr == NULL) { + bpf_printk("context offset ptr is null while context is not passed directly as an argument"); + return NULL; + } void *ctx_addr = get_go_interface_instance(arg + (*loc->context_offset_ptr)); void *ctx_val = 0; bpf_probe_read_user(&ctx_val, sizeof(ctx_val), ctx_addr); diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c index 885cbddcc..d8d4ebdf9 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c @@ -42,7 +42,7 @@ struct { // Injected in init volatile const bool should_include_db_statement; -struct go_context_loc queryDC_ctx_loc = { +volatile const struct go_context_loc queryDC_ctx_loc = { .context_pos = 3, .passed_as_arg = true, .context_offset_ptr = NULL, diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index 46aaf9140..37a3b3db7 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -46,7 +46,7 @@ volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; volatile const u64 ctx_ptr_pos; -struct go_context_loc GinEngine_ServeHTTP_ctx_loc = { +volatile const struct go_context_loc GinEngine_ServeHTTP_ctx_loc = { .context_pos = 4, .passed_as_arg = false, .context_offset_ptr = &ctx_ptr_pos, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index e0c7e07d4..5b6135c76 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -78,7 +78,7 @@ volatile const u64 httpclient_nextid_pos; volatile const u64 headerFrame_streamid_pos; volatile const u64 headerFrame_hf_pos; -struct go_context_loc ClientConn_Invoke_ctx_loc = { +volatile const struct go_context_loc ClientConn_Invoke_ctx_loc = { .context_pos = 3, .passed_as_arg = true, .context_offset_ptr = NULL, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index b8fc70c80..f5e375f31 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -68,7 +68,7 @@ volatile const u64 frame_stream_id_pod; volatile const u64 stream_id_pos; volatile const u64 stream_ctx_pos; -struct go_context_loc stream_ctx_loc = { +volatile const struct go_context_loc stream_ctx_loc = { .context_pos = 4, .passed_as_arg = false, .context_offset_ptr = &stream_ctx_pos, diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 51bd14e8e..84f134c48 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -145,7 +145,7 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context return 0; } -struct go_context_loc HttpClient_ctx_loc = { +volatile const struct go_context_loc HttpClient_ctx_loc = { .context_pos = 2, .passed_as_arg = false, .context_offset_ptr = &ctx_ptr_pos, diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 405f9596c..ae21a797e 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -131,6 +131,10 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi { continue; } + if (map_value->keys[i].str == NULL) + { + continue; + } char current_header_key[W3C_KEY_LENGTH]; bpf_probe_read(current_header_key, sizeof(current_header_key), map_value->keys[i].str); if (!bpf_memcmp(current_header_key, "traceparent", W3C_KEY_LENGTH) && !bpf_memcmp(current_header_key, "Traceparent", W3C_KEY_LENGTH)) @@ -167,7 +171,7 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi return NULL; } -struct go_context_loc ServeHTTP_ctx_loc = { +volatile const struct go_context_loc ServeHTTP_ctx_loc = { .context_pos = 4, .passed_as_arg = false, .context_offset_ptr = &ctx_ptr_pos, @@ -182,6 +186,10 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) u64 request_pos = 4; void *req_ptr = get_argument(ctx, request_pos); void *req_ctx_ptr = get_Go_context(ctx, &ServeHTTP_ctx_loc); + if (req_ctx_ptr == NULL) + { + return 0; + } void *key = get_consistent_key(ctx, req_ctx_ptr); void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) From c7142023a809a4033b1faa96feeaa0aac097109b Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 8 Oct 2023 18:25:22 +0300 Subject: [PATCH 51/67] Add get_go_string_from_user_ptr helper --- internal/include/alloc.h | 29 ++---------- internal/include/go_context.h | 44 +++++++------------ internal/include/go_types.h | 26 ++++++++++- internal/include/uprobe.h | 6 +-- .../bpf/database/sql/bpf/probe.bpf.c | 10 +---- .../github.com/gin-gonic/gin/bpf/probe.bpf.c | 10 +---- .../google.golang.org/grpc/bpf/probe.bpf.c | 23 +++------- .../grpc/server/bpf/probe.bpf.c | 24 ++++------ .../bpf/net/http/client/bpf/probe.bpf.c | 36 +++++---------- .../bpf/net/http/server/bpf/probe.bpf.c | 37 +++++----------- 10 files changed, 88 insertions(+), 157 deletions(-) diff --git a/internal/include/alloc.h b/internal/include/alloc.h index 6c3490f58..13b4dae80 100644 --- a/internal/include/alloc.h +++ b/internal/include/alloc.h @@ -102,29 +102,6 @@ static __always_inline void *write_target_data(void *data, s32 size) return NULL; } - // Add padding to align to 8 bytes - if (size % 8 != 0) { - size += 8 - (size % 8); - - // Write to the buffer - u32 key = 0; - void *buffer = bpf_map_lookup_elem(&alignment_buffer, &key); - if (buffer == NULL) { - bpf_printk("failed to get alignment buffer"); - return NULL; - } - - // Copy size bytes from data to buffer - size = bound_number(size, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE); - long success = bpf_probe_read(buffer, size, data); - if (success != 0) { - bpf_printk("failed to copy data to alignment buffer"); - return NULL; - } - - data = buffer; - } - u64 start = get_area_start(); u64 end = get_area_end(start); if (end - start < size) @@ -150,9 +127,9 @@ static __always_inline void *write_target_data(void *data, s32 size) u64 updated_start = start + size; // align updated_start to 8 bytes - // if (updated_start % 8 != 0) { - // updated_start += 8 - (updated_start % 8); - // } + if (updated_start % 8 != 0) { + updated_start += 8 - (updated_start % 8); + } bpf_map_update_elem(&alloc_map, &start_index, &updated_start, BPF_ANY); bpf_printk("wrote %d bytes to userspace at addr: %lx", size, target); diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 2c607b8d9..2a9fe9fe3 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -38,22 +38,6 @@ struct __uint(pinning, LIBBPF_PIN_BY_NAME); } tracked_spans_by_sc SEC(".maps"); -// Identifies the location of the context.Context in the function arguments -struct go_context_loc -{ - // The argument position of the context.Context data pointer - // In case the context.Context is passed as an argument, - // this is the argument index of the pointer (starting from 1). - // In case the context.Context is a member of a struct, - // this is the argument index of the struct pointer (starting from 1). - int context_pos; - // In case the context.Context is a member of a struct, - // this is the offset of the context.Context member in the struct. - const volatile u64 *context_offset_ptr; - // Indicates whether context.Context is passed as an argument or is a member of a struct - bool passed_as_arg; -}; - typedef struct span_context* (*get_parent_fb)(void*); static __always_inline void *get_parent_go_context(void *ctx, void *map) { @@ -127,20 +111,24 @@ static __always_inline void stop_tracking_span(struct span_context *sc, bool isR bpf_map_delete_elem(&tracked_spans_by_sc, sc); } -static __always_inline void *get_Go_context(void *ctx, struct go_context_loc *loc) { - if (loc == NULL) { - bpf_printk("go_context_loc is null"); - return NULL; - } - void *arg = get_argument(ctx, loc->context_pos); - if (loc->passed_as_arg) { +// Extract the go context.Context data pointer from the function arguments +// context_pos: + // The argument position of the context.Context data pointer + // In case the context.Context is passed as an argument, + // this is the argument index of the pointer (starting from 1). + // In case the context.Context is a member of a struct, + // this is the argument index of the struct pointer (starting from 1). +// context_offset: + // In case the context.Context is a member of a struct, + // this is the offset of the context.Context member in the struct. +// passed_as_arg: + // Indicates whether context.Context is passed as an argument or is a member of a struct +static __always_inline void *get_Go_context(void *ctx, int context_pos, const volatile u64 context_offset, bool passed_as_arg) { + void *arg = get_argument(ctx, context_pos); + if (passed_as_arg) { return arg; } - if (loc->context_offset_ptr == NULL) { - bpf_printk("context offset ptr is null while context is not passed directly as an argument"); - return NULL; - } - void *ctx_addr = get_go_interface_instance(arg + (*loc->context_offset_ptr)); + void *ctx_addr = get_go_interface_instance((void*)(arg + context_offset)); void *ctx_val = 0; bpf_probe_read_user(&ctx_val, sizeof(ctx_val), ctx_addr); return ctx_val; diff --git a/internal/include/go_types.h b/internal/include/go_types.h index 505ad97d9..dfd867937 100644 --- a/internal/include/go_types.h +++ b/internal/include/go_types.h @@ -89,7 +89,6 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n { if (slice->len < slice->cap) { - bpf_printk("room in slice ! len %d cap %d", slice->len, slice->cap); // Room available on current array bpf_probe_write_user(slice->array + (item_size * slice->len), new_item, item_size); } @@ -158,4 +157,29 @@ static __always_inline void append_item_to_slice(struct go_slice *slice, void *n return; } } + +static __always_inline bool get_go_string_from_user_ptr(void *user_str_ptr, char *dst, u64 max_len) +{ + if (user_str_ptr == NULL) + { + return false; + } + + struct go_string user_str = {0}; + long success = 0; + success = bpf_probe_read(&user_str, sizeof(struct go_string), user_str_ptr); + if (success != 0 || user_str.len < 1) + { + return false; + } + + u64 size_to_read = user_str.len > max_len ? max_len : user_str.len; + success = bpf_probe_read(dst, size_to_read, user_str.str); + if (success != 0) + { + return false; + } + + return true; +} #endif \ No newline at end of file diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index fdb3fed5e..997744804 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -33,13 +33,13 @@ // 4. Submit the constructed event to the agent code using perf buffer events_map // 5. Delete the span from the uprobe_context_map // 6. Delete the span from the global active spans map -#define UPROBE_RETURN(name, event_type, ctx_loc_ptr, uprobe_context_map, events_map, is_root) \ +#define UPROBE_RETURN(name, event_type, uprobe_context_map, events_map, is_root, context_pos, context_offset, passed_as_arg) \ SEC("uprobe/##name##") \ int uprobe_##name##_Returns(struct pt_regs *ctx) { \ - void *ctx_address = get_Go_context(ctx, ctx_loc_ptr); \ + void *ctx_address = get_Go_context(ctx, context_pos, context_offset, passed_as_arg); \ void *key = get_consistent_key(ctx, ctx_address); \ void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \ - event_type tmpReq = {}; \ + event_type tmpReq = {0}; \ bpf_probe_read(&tmpReq, sizeof(tmpReq), req_ptr_map); \ tmpReq.end_time = bpf_ktime_get_ns(); \ bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c index d8d4ebdf9..a1454aea2 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c @@ -42,12 +42,6 @@ struct { // Injected in init volatile const bool should_include_db_statement; -volatile const struct go_context_loc queryDC_ctx_loc = { - .context_pos = 3, - .passed_as_arg = true, - .context_offset_ptr = NULL, -}; - // This instrumentation attaches uprobe to the following function: // func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) SEC("uprobe/queryDC") @@ -69,7 +63,7 @@ int uprobe_queryDC(struct pt_regs *ctx) { } // Get parent if exists - void *context_ptr_val = get_Go_context(ctx, &queryDC_ctx_loc); + void *context_ptr_val = get_Go_context(ctx, 3, 0, true); struct span_context *span_ctx = get_parent_span_context(context_ptr_val); if (span_ctx != NULL) { // Set the parent context @@ -90,4 +84,4 @@ int uprobe_queryDC(struct pt_regs *ctx) { // This instrumentation attaches uprobe to the following function: // func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) -UPROBE_RETURN(queryDC, struct sql_request_t, &queryDC_ctx_loc, sql_events, events, false) \ No newline at end of file +UPROBE_RETURN(queryDC, struct sql_request_t, sql_events, events, false, 3, 0, true) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index 37a3b3db7..c7c481eea 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -46,12 +46,6 @@ volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; volatile const u64 ctx_ptr_pos; -volatile const struct go_context_loc GinEngine_ServeHTTP_ctx_loc = { - .context_pos = 4, - .passed_as_arg = false, - .context_offset_ptr = &ctx_ptr_pos, -}; - // This instrumentation attaches uprobe to the following function: // func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) SEC("uprobe/GinEngine_ServeHTTP") @@ -62,7 +56,7 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { // Get request struct void *req_ptr = get_argument(ctx, request_pos); - void *req_ctx_ptr = get_Go_context(ctx, &GinEngine_ServeHTTP_ctx_loc); + void *req_ctx_ptr = get_Go_context(ctx, 4, ctx_ptr_pos, false); // Get method from request void *method_ptr = 0; @@ -94,4 +88,4 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { return 0; } -UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, &GinEngine_ServeHTTP_ctx_loc, http_events, events, true) \ No newline at end of file +UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, http_events, events, true, 4, ctx_ptr_pos, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 5b6135c76..757708f07 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -78,12 +78,6 @@ volatile const u64 httpclient_nextid_pos; volatile const u64 headerFrame_streamid_pos; volatile const u64 headerFrame_hf_pos; -volatile const struct go_context_loc ClientConn_Invoke_ctx_loc = { - .context_pos = 3, - .passed_as_arg = true, - .context_offset_ptr = NULL, -}; - // This instrumentation attaches uprobe to the following function: // func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error SEC("uprobe/ClientConn_Invoke") @@ -106,16 +100,14 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) // Read ClientConn.Target void *clientconn_ptr = get_argument(ctx, clientconn_pos); - void *target_ptr = 0; - bpf_probe_read(&target_ptr, sizeof(target_ptr), (void *)(clientconn_ptr + (clientconn_target_ptr_pos))); - u64 target_len = 0; - bpf_probe_read(&target_len, sizeof(target_len), (void *)(clientconn_ptr + (clientconn_target_ptr_pos + 8))); - u64 target_size = sizeof(grpcReq.target); - target_size = target_size < target_len ? target_size : target_len; - bpf_probe_read(&grpcReq.target, target_size, target_ptr); + if (!get_go_string_from_user_ptr((void*)(clientconn_ptr + clientconn_target_ptr_pos), grpcReq.target, sizeof(grpcReq.target))) + { + bpf_printk("target write failed, aborting ebpf probe"); + return 0; + } // Get parent if exists - void *context_ptr = get_Go_context(ctx, &ClientConn_Invoke_ctx_loc); + void *context_ptr = get_Go_context(ctx, 3, 0, true); struct span_context *parent_span_ctx = get_parent_span_context(context_ptr); if (parent_span_ctx != NULL) { @@ -137,7 +129,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, &ClientConn_Invoke_ctx_loc, grpc_events, events, false) +UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, grpc_events, events, false, 3, 0, true) // func (l *loopyWriter) headerHandler(h *headerFrame) error SEC("uprobe/loopyWriter_headerHandler") @@ -183,7 +175,6 @@ int uprobe_LoopyWriter_HeaderHandler(struct pt_regs *ctx) struct hpack_header_field hf = {}; hf.name = key_str; hf.value = val_str; - bpf_printk("item size %d", sizeof(hf)); append_item_to_slice(&slice, &hf, sizeof(hf), &slice_user_ptr, &headers_buff_map); return 0; } diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index f5e375f31..31d262605 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -68,12 +68,6 @@ volatile const u64 frame_stream_id_pod; volatile const u64 stream_id_pos; volatile const u64 stream_ctx_pos; -volatile const struct go_context_loc stream_ctx_loc = { - .context_pos = 4, - .passed_as_arg = false, - .context_offset_ptr = &stream_ctx_pos, -}; - // This instrumentation attaches uprobe to the following function: // func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) { SEC("uprobe/server_handleStream") @@ -87,6 +81,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) bpf_probe_read(&stream_id, sizeof(stream_id), (void *)(stream_ptr + stream_id_pos)); void *grpcReq_ptr = bpf_map_lookup_elem(&streamid_to_grpc_events, &stream_id); struct grpc_request_t grpcReq = {}; + grpcReq.start_time = bpf_ktime_get_ns(); if (grpcReq_ptr != NULL) { bpf_probe_read(&grpcReq, sizeof(grpcReq), grpcReq_ptr); @@ -100,17 +95,14 @@ int uprobe_server_handleStream(struct pt_regs *ctx) } // Set attributes - grpcReq.start_time = bpf_ktime_get_ns(); - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(stream_ptr + stream_method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(stream_ptr + (stream_method_ptr_pos + 8))); - u64 method_size = sizeof(grpcReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&grpcReq.method, method_size, method_ptr); + if (!get_go_string_from_user_ptr((void *)(stream_ptr + stream_method_ptr_pos), grpcReq.method, sizeof(grpcReq.method))) + { + bpf_printk("method write failed, aborting ebpf probe"); + return 0; + } // Get key - void *ctx_iface = get_Go_context(ctx, &stream_ctx_loc); + void *ctx_iface = get_Go_context(ctx, 4, stream_ctx_pos, false); void *key = get_consistent_key(ctx, ctx_iface); // Write event @@ -119,7 +111,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(server_handleStream, struct grpc_request_t, &stream_ctx_loc, grpc_events, events, true) +UPROBE_RETURN(server_handleStream, struct grpc_request_t, grpc_events, events, true, 4, stream_ctx_pos, false) // func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error SEC("uprobe/decodeState_decodeHeader") diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 84f134c48..571f2872c 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -145,12 +145,6 @@ static __always_inline long inject_header(void* headers_ptr, struct span_context return 0; } -volatile const struct go_context_loc HttpClient_ctx_loc = { - .context_pos = 2, - .passed_as_arg = false, - .context_offset_ptr = &ctx_ptr_pos, -}; - // This instrumentation attaches uprobe to the following function: // func net/http/client.Do(req *Request) SEC("uprobe/HttpClient_Do") @@ -162,7 +156,7 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { void *req_ptr = get_argument(ctx, request_pos); // Get parent if exists - void *context_ptr_val = get_Go_context(ctx, &HttpClient_ctx_loc); + void *context_ptr_val = get_Go_context(ctx, 2, ctx_ptr_pos, false); void *key = get_consistent_key(ctx, context_ptr_val); void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) @@ -170,7 +164,6 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { bpf_printk("client: httpReq_ptr is not null"); return 0; } - //void *context_ptr = (void *)(req_ptr+ctx_ptr_pos); struct span_context *parent_span_ctx = get_parent_span_context(context_ptr_val); if (parent_span_ctx != NULL) { @@ -181,31 +174,22 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { httpReq.sc = generate_span_context(); } - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr+method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr+(method_ptr_pos+8))); - u64 method_size = sizeof(httpReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&httpReq.method, method_size, method_ptr); + if (!get_go_string_from_user_ptr((void *)(req_ptr+method_ptr_pos), httpReq.method, sizeof(httpReq.method))) { + bpf_printk("uprobe_HttpClient_Do: Failed to get method from request"); + return 0; + } // get path from Request.URL void *url_ptr = 0; bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr+url_ptr_pos)); - void *path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr+path_ptr_pos)); - - u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr+(path_ptr_pos+8))); - u64 path_size = sizeof(httpReq.path); - path_size = path_size < path_len ? path_size : path_len; - bpf_probe_read(&httpReq.path, path_size, path_ptr); + if (!get_go_string_from_user_ptr((void *)(url_ptr+path_ptr_pos), httpReq.path, sizeof(httpReq.path))) { + bpf_printk("uprobe_HttpClient_Do: Failed to get path from Request.URL"); + return 0; + } // get headers from Request void *headers_ptr = 0; bpf_probe_read(&headers_ptr, sizeof(headers_ptr), (void *)(req_ptr+headers_ptr_pos)); - u64 map_keyvalue_count = 0; - bpf_probe_read(&map_keyvalue_count, sizeof(map_keyvalue_count), headers_ptr); long res = inject_header(headers_ptr, &httpReq.sc); if (res < 0) { bpf_printk("uprobe_HttpClient_Do: Failed to inject header"); @@ -219,4 +203,4 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // This instrumentation attaches uretprobe to the following function: // func net/http/client.Do(req *Request) -UPROBE_RETURN(HttpClient_Do, struct http_request_t, &HttpClient_ctx_loc, http_events, events, true) \ No newline at end of file +UPROBE_RETURN(HttpClient_Do, struct http_request_t, http_events, events, true, 2, ctx_ptr_pos, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index ae21a797e..1f018b686 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -171,12 +171,6 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi return NULL; } -volatile const struct go_context_loc ServeHTTP_ctx_loc = { - .context_pos = 4, - .passed_as_arg = false, - .context_offset_ptr = &ctx_ptr_pos, -}; - // This instrumentation attaches uprobe to the following function: // func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) SEC("uprobe/HandlerFunc_ServeHTTP") @@ -185,7 +179,7 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) // Get key u64 request_pos = 4; void *req_ptr = get_argument(ctx, request_pos); - void *req_ctx_ptr = get_Go_context(ctx, &ServeHTTP_ctx_loc); + void *req_ctx_ptr = get_Go_context(ctx, 4, ctx_ptr_pos, false); if (req_ctx_ptr == NULL) { return 0; @@ -201,28 +195,21 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) struct http_request_t httpReq = {}; httpReq.start_time = bpf_ktime_get_ns(); - // Get method from request - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr + method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr + (method_ptr_pos + 8))); - u64 method_size = sizeof(httpReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&httpReq.method, method_size, method_ptr); - + // // Get method from request + if (!get_go_string_from_user_ptr((void *)(req_ptr + method_ptr_pos), httpReq.method, sizeof(httpReq.method))) { + bpf_printk("failed to get method from request"); + return 0; + } // get path from Request.URL void *url_ptr = 0; bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr + url_ptr_pos)); - void *path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr + path_ptr_pos)); - u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr + (path_ptr_pos + 8))); - u64 path_size = sizeof(httpReq.path); - path_size = path_size < path_len ? path_size : path_len; - bpf_probe_read(&httpReq.path, path_size, path_ptr); + if (!get_go_string_from_user_ptr((void *)(url_ptr + path_ptr_pos), httpReq.path, sizeof(httpReq.path))) { + bpf_printk("failed to get path from Request.URL"); + return 0; + } // Propagate context - struct span_context *parent_ctx = extract_context_from_req_headers(req_ptr + headers_ptr_pos); + struct span_context *parent_ctx = extract_context_from_req_headers((void*)(req_ptr + headers_ptr_pos)); if (parent_ctx != NULL) { // found parent context in http headers @@ -241,4 +228,4 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(HandlerFunc_ServeHTTP, struct http_request_t, &ServeHTTP_ctx_loc, http_events, events, true) \ No newline at end of file +UPROBE_RETURN(HandlerFunc_ServeHTTP, struct http_request_t, http_events, events, true, 4, ctx_ptr_pos, false) \ No newline at end of file From 4b1bb68900437c6535e5c180bffef3116a62e305 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 8 Oct 2023 20:52:28 +0300 Subject: [PATCH 52/67] fix start time at grpc server --- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 2 +- .../pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 31d262605..60256da02 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -81,7 +81,6 @@ int uprobe_server_handleStream(struct pt_regs *ctx) bpf_probe_read(&stream_id, sizeof(stream_id), (void *)(stream_ptr + stream_id_pos)); void *grpcReq_ptr = bpf_map_lookup_elem(&streamid_to_grpc_events, &stream_id); struct grpc_request_t grpcReq = {}; - grpcReq.start_time = bpf_ktime_get_ns(); if (grpcReq_ptr != NULL) { bpf_probe_read(&grpcReq, sizeof(grpcReq), grpcReq_ptr); @@ -94,6 +93,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) grpcReq.sc = generate_span_context(); } + grpcReq.start_time = bpf_ktime_get_ns(); // Set attributes if (!get_go_string_from_user_ptr((void *)(stream_ptr + stream_method_ptr_pos), grpcReq.method, sizeof(grpcReq.method))) { diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 1f018b686..5a527dc8d 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -131,10 +131,6 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi { continue; } - if (map_value->keys[i].str == NULL) - { - continue; - } char current_header_key[W3C_KEY_LENGTH]; bpf_probe_read(current_header_key, sizeof(current_header_key), map_value->keys[i].str); if (!bpf_memcmp(current_header_key, "traceparent", W3C_KEY_LENGTH) && !bpf_memcmp(current_header_key, "Traceparent", W3C_KEY_LENGTH)) From 5f7b9c2fe8c358792f1b2f30e2ac126744a146f9 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 8 Oct 2023 21:15:32 +0300 Subject: [PATCH 53/67] mem alloc fixup --- internal/include/alloc.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/include/alloc.h b/internal/include/alloc.h index 13b4dae80..1ae03747a 100644 --- a/internal/include/alloc.h +++ b/internal/include/alloc.h @@ -53,9 +53,6 @@ static __always_inline u64 get_area_start() if (start == NULL || *start == 0) { u64 current_start_addr = start_addr + (partition_size * current_cpu); - if (current_start_addr % 8 != 0) { - current_start_addr += 8 - (current_start_addr % 8); - } bpf_map_update_elem(&alloc_map, &start_index, ¤t_start_addr, BPF_ANY); return current_start_addr; } From f497a5d43a9f55121c899267b9beb12a4ba52ac0 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sun, 8 Oct 2023 23:30:01 +0300 Subject: [PATCH 54/67] reduce allocation --- internal/pkg/process/analyze.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index 3dd9c486c..14f00ca20 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -140,7 +140,7 @@ func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*Targ result.GoVersion = goVersion result.Libraries = modules - mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 50) + mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 8) addr, err := a.remoteMmap(pid, mapSize) if err != nil { log.Logger.Error(err, "Failed to mmap") From ef34a950aaf6649431ade8717da2dc13991e344d Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Mon, 9 Oct 2023 14:36:34 +0300 Subject: [PATCH 55/67] Add Allocater --- instrumentation.go | 6 +++ internal/pkg/process/allocate.go | 87 ++++++++++++++++++++++++++++++++ internal/pkg/process/analyze.go | 60 ---------------------- 3 files changed, 93 insertions(+), 60 deletions(-) create mode 100644 internal/pkg/process/allocate.go diff --git a/instrumentation.go b/instrumentation.go index 5e9c1eb11..95ad0938b 100644 --- a/instrumentation.go +++ b/instrumentation.go @@ -84,6 +84,12 @@ func NewInstrumentation(opts ...InstrumentationOption) (*Instrumentation, error) return nil, err } + allocDetails, err := process.Allocate(pid) + if err != nil { + return nil, err + } + td.AllocationDetails = allocDetails + if log.Logger.IsZero() { err := log.Init() if err != nil { diff --git a/internal/pkg/process/allocate.go b/internal/pkg/process/allocate.go new file mode 100644 index 000000000..f8fb03442 --- /dev/null +++ b/internal/pkg/process/allocate.go @@ -0,0 +1,87 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package process + +import ( + "fmt" + "os" + "runtime" + + "go.opentelemetry.io/auto/internal/pkg/log" + "go.opentelemetry.io/auto/internal/pkg/process/ptrace" +) + +// AllocationDetails are the details about allocated memory. +type AllocationDetails struct { + StartAddr uint64 + EndAddr uint64 +} + +// Allocate allocates memory for the instrumented process. +func Allocate(pid int) (*AllocationDetails, error) { + mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 8) + addr, err := remoteAllocate(pid, mapSize) + + if err != nil { + log.Logger.Error(err, "Failed to mmap") + return nil, err + } + + log.Logger.V(0).Info("mmaped remote memory", "start_addr", fmt.Sprintf("%X", addr), + "end_addr", fmt.Sprintf("%X", addr+mapSize)) + + return &AllocationDetails{ + StartAddr: addr, + EndAddr: addr + mapSize, + }, nil +} + +func remoteAllocate(pid int, mapSize uint64) (uint64, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + program, err := ptrace.NewTracedProgram(pid, log.Logger) + if err != nil { + log.Logger.Error(err, "Failed to attach ptrace", "pid", pid) + return 0, err + } + + defer func() { + log.Logger.V(0).Info("Detaching from process", "pid", pid) + err := program.Detach() + if err != nil { + log.Logger.Error(err, "Failed to detach ptrace", "pid", pid) + } + }() + fd := -1 + addr, err := program.Mmap(mapSize, uint64(fd)) + if err != nil { + log.Logger.Error(err, "Failed to mmap", "pid", pid) + return 0, err + } + + err = program.Madvise(addr, mapSize) + if err != nil { + log.Logger.Error(err, "Failed to madvise", "pid", pid) + return 0, err + } + + err = program.Mlock(addr, mapSize) + if err != nil { + log.Logger.Error(err, "Failed to mlock", "pid", pid) + return 0, err + } + + return addr, nil +} \ No newline at end of file diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index 14f00ca20..10c4a485f 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -19,12 +19,10 @@ import ( "errors" "fmt" "os" - "runtime" "github.com/hashicorp/go-version" "go.opentelemetry.io/auto/internal/pkg/log" - "go.opentelemetry.io/auto/internal/pkg/process/ptrace" ) // TargetDetails are the details about a target function. @@ -36,12 +34,6 @@ type TargetDetails struct { AllocationDetails *AllocationDetails } -// AllocationDetails are the details about allocated memory. -type AllocationDetails struct { - StartAddr uint64 - EndAddr uint64 -} - // Func represents a function target. type Func struct { Name string @@ -78,44 +70,6 @@ func (t *TargetDetails) GetFunctionReturns(name string) ([]uint64, error) { return nil, fmt.Errorf("could not find returns for function %s", name) } -func (a *Analyzer) remoteMmap(pid int, mapSize uint64) (uint64, error) { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - program, err := ptrace.NewTracedProgram(pid, log.Logger) - if err != nil { - log.Logger.Error(err, "Failed to attach ptrace", "pid", pid) - return 0, err - } - - defer func() { - log.Logger.V(0).Info("Detaching from process", "pid", pid) - err := program.Detach() - if err != nil { - log.Logger.Error(err, "Failed to detach ptrace", "pid", pid) - } - }() - fd := -1 - addr, err := program.Mmap(mapSize, uint64(fd)) - if err != nil { - log.Logger.Error(err, "Failed to mmap", "pid", pid) - return 0, err - } - - err = program.Madvise(addr, mapSize) - if err != nil { - log.Logger.Error(err, "Failed to madvise", "pid", pid) - return 0, err - } - - err = program.Mlock(addr, mapSize) - if err != nil { - log.Logger.Error(err, "Failed to mlock", "pid", pid) - return 0, err - } - - return addr, nil -} - // Analyze returns the target details for an actively running process. func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*TargetDetails, error) { result := &TargetDetails{ @@ -140,20 +94,6 @@ func (a *Analyzer) Analyze(pid int, relevantFuncs map[string]interface{}) (*Targ result.GoVersion = goVersion result.Libraries = modules - mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 8) - addr, err := a.remoteMmap(pid, mapSize) - if err != nil { - log.Logger.Error(err, "Failed to mmap") - return nil, err - } - log.Logger.V(0).Info("mmaped remote memory", "start_addr", fmt.Sprintf("%X", addr), - "end_addr", fmt.Sprintf("%X", addr+mapSize)) - - result.AllocationDetails = &AllocationDetails{ - StartAddr: addr, - EndAddr: addr + mapSize, - } - if err != nil { return nil, err } From 4b7bc3717cfd15ac77da9bb1ba4c50a7effa6af6 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 10 Oct 2023 02:00:24 +0300 Subject: [PATCH 56/67] remove unused definition --- internal/include/go_context.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 2a9fe9fe3..5d9f6e0bf 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -38,8 +38,6 @@ struct __uint(pinning, LIBBPF_PIN_BY_NAME); } tracked_spans_by_sc SEC(".maps"); -typedef struct span_context* (*get_parent_fb)(void*); - static __always_inline void *get_parent_go_context(void *ctx, void *map) { void *data = ctx; for (int i = 0; i < MAX_DISTANCE; i++) From 1bf1fd02be93b271615bcaad5f7b2b0282a464cc Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 10 Oct 2023 11:07:56 +0300 Subject: [PATCH 57/67] add logic to stop_tracking_span --- internal/include/go_context.h | 34 +++++++++++++++++++++++++++------- internal/include/uprobe.h | 3 +-- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 5d9f6e0bf..03b5be2d6 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -95,17 +95,37 @@ static __always_inline void start_tracking_span(void *contextContext, struct spa } } -static __always_inline void stop_tracking_span(struct span_context *sc, bool isRoot) { - if (isRoot) +static __always_inline void stop_tracking_span(struct span_context *sc, struct span_context *psc) { + if (psc == NULL || sc == NULL) { + bpf_printk("stop_tracking_span: psc or sc is null"); + return; + } + + void *ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, sc); + if (ctx == NULL) { - void *ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, sc); - if (ctx == NULL) - { - return; - } + bpf_printk("stop_tracking_span: cant find span context"); + return; + } + void *parent_ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, psc); + if (parent_ctx == NULL) + { bpf_map_delete_elem(&tracked_spans, ctx); + } else + { + void *ctx_val = 0; + bpf_probe_read_user(&ctx_val, sizeof(ctx_val), ctx); + void *parent_ctx_val = 0; + bpf_probe_read_user(&parent_ctx_val, sizeof(parent_ctx_val), parent_ctx); + + if (ctx_val != parent_ctx_val) + { + bpf_printk("stop_tracking_span: ctx_val != parent_ctx_val"); + bpf_map_delete_elem(&tracked_spans, ctx); + } } + bpf_map_delete_elem(&tracked_spans_by_sc, sc); } diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index 997744804..3f728edf6 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -44,8 +44,7 @@ int uprobe_##name##_Returns(struct pt_regs *ctx) { tmpReq.end_time = bpf_ktime_get_ns(); \ bpf_perf_event_output(ctx, &events_map, BPF_F_CURRENT_CPU, &tmpReq, sizeof(tmpReq)); \ bpf_map_delete_elem(&uprobe_context_map, &key); \ - bool is_local_root = (is_root || bpf_is_zero(tmpReq.psc.SpanID, sizeof(tmpReq.psc.SpanID))); \ - stop_tracking_span(&tmpReq.sc, is_local_root); \ + stop_tracking_span(&tmpReq.sc, &tmpReq.psc); \ return 0; \ } From 296f4fd80ad7c90e7d4e5d67968181a222bc5e8b Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 10 Oct 2023 16:28:46 +0300 Subject: [PATCH 58/67] handle error at uprobe_return --- internal/include/uprobe.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index 3f728edf6..ebb1852e3 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -39,6 +39,9 @@ int uprobe_##name##_Returns(struct pt_regs *ctx) { void *ctx_address = get_Go_context(ctx, context_pos, context_offset, passed_as_arg); \ void *key = get_consistent_key(ctx, ctx_address); \ void *req_ptr_map = bpf_map_lookup_elem(&uprobe_context_map, &key); \ + if (req_ptr_map == NULL) { \ + return 0; \ + } \ event_type tmpReq = {0}; \ bpf_probe_read(&tmpReq, sizeof(tmpReq), req_ptr_map); \ tmpReq.end_time = bpf_ktime_get_ns(); \ From a89548ccd49ac23bc89aac18060d41cce9687c70 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 10 Oct 2023 17:16:09 +0300 Subject: [PATCH 59/67] Remove root arg for uprobe_return --- internal/include/uprobe.h | 2 +- internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c | 2 +- .../instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c | 2 +- .../instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c | 2 +- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 2 +- internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c | 2 +- internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/include/uprobe.h b/internal/include/uprobe.h index ebb1852e3..655c97509 100644 --- a/internal/include/uprobe.h +++ b/internal/include/uprobe.h @@ -33,7 +33,7 @@ // 4. Submit the constructed event to the agent code using perf buffer events_map // 5. Delete the span from the uprobe_context_map // 6. Delete the span from the global active spans map -#define UPROBE_RETURN(name, event_type, uprobe_context_map, events_map, is_root, context_pos, context_offset, passed_as_arg) \ +#define UPROBE_RETURN(name, event_type, uprobe_context_map, events_map, context_pos, context_offset, passed_as_arg) \ SEC("uprobe/##name##") \ int uprobe_##name##_Returns(struct pt_regs *ctx) { \ void *ctx_address = get_Go_context(ctx, context_pos, context_offset, passed_as_arg); \ diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c index a1454aea2..85e443a3e 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf/probe.bpf.c @@ -84,4 +84,4 @@ int uprobe_queryDC(struct pt_regs *ctx) { // This instrumentation attaches uprobe to the following function: // func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) -UPROBE_RETURN(queryDC, struct sql_request_t, sql_events, events, false, 3, 0, true) \ No newline at end of file +UPROBE_RETURN(queryDC, struct sql_request_t, sql_events, events, 3, 0, true) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index c7c481eea..d69579cf1 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -88,4 +88,4 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { return 0; } -UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, http_events, events, true, 4, ctx_ptr_pos, false) \ No newline at end of file +UPROBE_RETURN(GinEngine_ServeHTTP, struct http_request_t, http_events, events, 4, ctx_ptr_pos, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index 757708f07..e9fa07573 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -129,7 +129,7 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, grpc_events, events, false, 3, 0, true) +UPROBE_RETURN(ClientConn_Invoke, struct grpc_request_t, grpc_events, events, 3, 0, true) // func (l *loopyWriter) headerHandler(h *headerFrame) error SEC("uprobe/loopyWriter_headerHandler") diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 60256da02..3f3876968 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -111,7 +111,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(server_handleStream, struct grpc_request_t, grpc_events, events, true, 4, stream_ctx_pos, false) +UPROBE_RETURN(server_handleStream, struct grpc_request_t, grpc_events, events, 4, stream_ctx_pos, false) // func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error SEC("uprobe/decodeState_decodeHeader") diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 571f2872c..14b4a2ec8 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -203,4 +203,4 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // This instrumentation attaches uretprobe to the following function: // func net/http/client.Do(req *Request) -UPROBE_RETURN(HttpClient_Do, struct http_request_t, http_events, events, true, 2, ctx_ptr_pos, false) \ No newline at end of file +UPROBE_RETURN(HttpClient_Do, struct http_request_t, http_events, events, 2, ctx_ptr_pos, false) \ No newline at end of file diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 5a527dc8d..b7967a5a0 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -224,4 +224,4 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) return 0; } -UPROBE_RETURN(HandlerFunc_ServeHTTP, struct http_request_t, http_events, events, true, 4, ctx_ptr_pos, false) \ No newline at end of file +UPROBE_RETURN(HandlerFunc_ServeHTTP, struct http_request_t, http_events, events, 4, ctx_ptr_pos, false) \ No newline at end of file From eed4cd8bf09a2e2753fad036c894891fc19e7473 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 10 Oct 2023 17:59:55 +0300 Subject: [PATCH 60/67] remove unused import --- internal/pkg/process/analyze.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/pkg/process/analyze.go b/internal/pkg/process/analyze.go index b57d6fdef..10c4a485f 100644 --- a/internal/pkg/process/analyze.go +++ b/internal/pkg/process/analyze.go @@ -19,7 +19,6 @@ import ( "errors" "fmt" "os" - "runtime" "github.com/hashicorp/go-version" From 51f372ab7e8ffb7f8f5ed056282084f975f592bf Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Tue, 10 Oct 2023 23:40:13 +0300 Subject: [PATCH 61/67] Cleanup --- CHANGELOG.md | 1 + internal/include/alloc.h | 10 --------- .../bpf/database/sql/bpf_bpfel_arm64.go | 3 --- .../bpf/database/sql/bpf_bpfel_x86.go | 3 --- .../github.com/gin-gonic/gin/bpf/probe.bpf.c | 22 +++++++------------ .../gin-gonic/gin/bpf_bpfel_arm64.go | 3 --- .../github.com/gin-gonic/gin/bpf_bpfel_x86.go | 3 --- .../google.golang.org/grpc/bpf_bpfel_arm64.go | 3 --- .../google.golang.org/grpc/bpf_bpfel_x86.go | 3 --- .../grpc/server/bpf_bpfel_arm64.go | 3 --- .../grpc/server/bpf_bpfel_x86.go | 3 --- .../bpf/net/http/client/bpf_bpfel_arm64.go | 3 --- .../bpf/net/http/client/bpf_bpfel_x86.go | 3 --- .../bpf/net/http/server/bpf/probe.bpf.c | 2 +- .../bpf/net/http/server/bpf_bpfel_arm64.go | 3 --- .../bpf/net/http/server/bpf_bpfel_x86.go | 3 --- internal/pkg/instrumentors/utils/kernel.go | 16 +++++++++++++- internal/pkg/process/allocate.go | 4 ++-- internal/pkg/process/ptrace/ptrace_linux.go | 4 ++-- 19 files changed, 29 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4906d8e82..f8d4d9985 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http - Fix bug in the `net/http` server instrumentation which always created a new span context. ([#266]https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/266) - Fix runtime panic if OTEL_GO_AUTO_TARGET_EXE is not set. ([#339](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/339)) +- Improve eBPF context propagation stability ([#368]https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/368) ### Deprecated diff --git a/internal/include/alloc.h b/internal/include/alloc.h index 1ae03747a..f4d94b09b 100644 --- a/internal/include/alloc.h +++ b/internal/include/alloc.h @@ -35,15 +35,6 @@ struct __uint(pinning, LIBBPF_PIN_BY_NAME); } alloc_map SEC(".maps"); -// Buffer for aligned data -struct -{ - __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __uint(key_size, sizeof(u32)); - __uint(value_size, MAX_BUFFER_SIZE); - __uint(max_entries, 1); -} alignment_buffer SEC(".maps"); - static __always_inline u64 get_area_start() { s64 partition_size = (end_addr - start_addr) / total_cpus; @@ -129,7 +120,6 @@ static __always_inline void *write_target_data(void *data, s32 size) } bpf_map_update_elem(&alloc_map, &start_index, &updated_start, BPF_ANY); - bpf_printk("wrote %d bytes to userspace at addr: %lx", size, target); return target; } else diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go index 478622e4f..18fa1aa93 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_arm64.go @@ -75,7 +75,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` SqlEvents *ebpf.MapSpec `ebpf:"sql_events"` @@ -102,7 +101,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` SqlEvents *ebpf.Map `ebpf:"sql_events"` @@ -112,7 +110,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.SqlEvents, diff --git a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go index 9f250fc76..86185db34 100644 --- a/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/database/sql/bpf_bpfel_x86.go @@ -75,7 +75,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` SqlEvents *ebpf.MapSpec `ebpf:"sql_events"` @@ -102,7 +101,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` SqlEvents *ebpf.Map `ebpf:"sql_events"` @@ -112,7 +110,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.SqlEvents, diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index d69579cf1..8108c2490 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -59,24 +59,18 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { void *req_ctx_ptr = get_Go_context(ctx, 4, ctx_ptr_pos, false); // Get method from request - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr + method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr + (method_ptr_pos + 8))); - u64 method_size = sizeof(httpReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&httpReq.method, method_size, method_ptr); + if (!get_go_string_from_user_ptr((void *)(req_ptr + method_ptr_pos), httpReq.method, sizeof(httpReq.method))) { + bpf_printk("failed to get method from request"); + return 0; + } // get path from Request.URL void *url_ptr = 0; bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr + url_ptr_pos)); - void *path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr + path_ptr_pos)); - u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr + (path_ptr_pos + 8))); - u64 path_size = sizeof(httpReq.path); - path_size = path_size < path_len ? path_size : path_len; - bpf_probe_read(&httpReq.path, path_size, path_ptr); + if (!get_go_string_from_user_ptr((void *)(url_ptr + path_ptr_pos), httpReq.path, sizeof(httpReq.path))) { + bpf_printk("failed to get path from Request.URL"); + return 0; + } // Get key void *key = get_consistent_key(ctx, req_ctx_ptr); diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go index 4164a79e8..e58fa7b54 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` @@ -103,7 +102,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` HttpEvents *ebpf.Map `ebpf:"http_events"` @@ -113,7 +111,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.HttpEvents, diff --git a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go index 9a15b0cb8..9d8998f16 100644 --- a/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` HttpEvents *ebpf.MapSpec `ebpf:"http_events"` @@ -103,7 +102,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` HttpEvents *ebpf.Map `ebpf:"http_events"` @@ -113,7 +111,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.HttpEvents, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go index 5535c1ac6..489bb8978 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_arm64.go @@ -80,7 +80,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -109,7 +108,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -121,7 +119,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go index c75a14d2f..f26a8e07e 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf_bpfel_x86.go @@ -80,7 +80,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -109,7 +108,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -121,7 +119,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go index 120e170e2..8002c33ab 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_arm64.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -104,7 +103,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -115,7 +113,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go index 624ee586b..db9a7611c 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf_bpfel_x86.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GrpcEvents *ebpf.MapSpec `ebpf:"grpc_events"` @@ -104,7 +103,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GrpcEvents *ebpf.Map `ebpf:"grpc_events"` @@ -115,7 +113,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GrpcEvents, diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go index 197fba15a..6846ab481 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_arm64.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -104,7 +103,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -115,7 +113,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go index 8f049cd61..6352e91da 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf_bpfel_x86.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -104,7 +103,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -115,7 +113,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index b7967a5a0..7e90e188e 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -191,7 +191,7 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) struct http_request_t httpReq = {}; httpReq.start_time = bpf_ktime_get_ns(); - // // Get method from request + // Get method from request if (!get_go_string_from_user_ptr((void *)(req_ptr + method_ptr_pos), httpReq.method, sizeof(httpReq.method))) { bpf_printk("failed to get method from request"); return 0; diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go index a62b33a43..c956cb2cd 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -105,7 +104,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -117,7 +115,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go index 23d51ea5d..b82c8fd2b 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go @@ -76,7 +76,6 @@ type bpfProgramSpecs struct { // // It can be passed ebpf.CollectionSpec.Assign. type bpfMapSpecs struct { - AlignmentBuffer *ebpf.MapSpec `ebpf:"alignment_buffer"` AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` Events *ebpf.MapSpec `ebpf:"events"` GolangMapbucketStorageMap *ebpf.MapSpec `ebpf:"golang_mapbucket_storage_map"` @@ -105,7 +104,6 @@ func (o *bpfObjects) Close() error { // // It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. type bpfMaps struct { - AlignmentBuffer *ebpf.Map `ebpf:"alignment_buffer"` AllocMap *ebpf.Map `ebpf:"alloc_map"` Events *ebpf.Map `ebpf:"events"` GolangMapbucketStorageMap *ebpf.Map `ebpf:"golang_mapbucket_storage_map"` @@ -117,7 +115,6 @@ type bpfMaps struct { func (m *bpfMaps) Close() error { return _BpfClose( - m.AlignmentBuffer, m.AllocMap, m.Events, m.GolangMapbucketStorageMap, diff --git a/internal/pkg/instrumentors/utils/kernel.go b/internal/pkg/instrumentors/utils/kernel.go index b5b1c8206..88428c298 100644 --- a/internal/pkg/instrumentors/utils/kernel.go +++ b/internal/pkg/instrumentors/utils/kernel.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package utils import ( @@ -25,4 +39,4 @@ func GetLinuxKernelVersion() (*version.Version, error) { } return version.NewVersion(ver) -} \ No newline at end of file +} diff --git a/internal/pkg/process/allocate.go b/internal/pkg/process/allocate.go index f8fb03442..bd9f9aca2 100644 --- a/internal/pkg/process/allocate.go +++ b/internal/pkg/process/allocate.go @@ -50,7 +50,7 @@ func Allocate(pid int) (*AllocationDetails, error) { func remoteAllocate(pid int, mapSize uint64) (uint64, error) { runtime.LockOSThread() - defer runtime.UnlockOSThread() + defer runtime.UnlockOSThread() program, err := ptrace.NewTracedProgram(pid, log.Logger) if err != nil { log.Logger.Error(err, "Failed to attach ptrace", "pid", pid) @@ -84,4 +84,4 @@ func remoteAllocate(pid int, mapSize uint64) (uint64, error) { } return addr, nil -} \ No newline at end of file +} diff --git a/internal/pkg/process/ptrace/ptrace_linux.go b/internal/pkg/process/ptrace/ptrace_linux.go index 27c4b9bef..4660560d0 100644 --- a/internal/pkg/process/ptrace/ptrace_linux.go +++ b/internal/pkg/process/ptrace/ptrace_linux.go @@ -22,9 +22,9 @@ import ( "syscall" "github.com/go-logr/logr" + "github.com/hashicorp/go-version" "github.com/pkg/errors" "go.opentelemetry.io/auto/internal/pkg/instrumentors/utils" - "github.com/hashicorp/go-version" "go.opentelemetry.io/auto/internal/pkg/log" ) @@ -241,4 +241,4 @@ func (p *TracedProgram) Mlock(addr uint64, length uint64) error { ret, err := p.Syscall(syscall.SYS_MLOCK, addr, length, 0, 0, 0, 0) log.Logger.V(0).Info("mlock ret", "ret", ret) return err -} \ No newline at end of file +} From 692a3917966bb3e6884bd6667360d98133e66137 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 11 Oct 2023 00:30:27 +0300 Subject: [PATCH 62/67] Fix linter --- internal/pkg/process/allocate.go | 1 - internal/pkg/process/ptrace/ptrace_linux.go | 9 ++++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/pkg/process/allocate.go b/internal/pkg/process/allocate.go index bd9f9aca2..c7d9adb2e 100644 --- a/internal/pkg/process/allocate.go +++ b/internal/pkg/process/allocate.go @@ -33,7 +33,6 @@ type AllocationDetails struct { func Allocate(pid int) (*AllocationDetails, error) { mapSize := uint64(os.Getpagesize() * runtime.NumCPU() * 8) addr, err := remoteAllocate(pid, mapSize) - if err != nil { log.Logger.Error(err, "Failed to mmap") return nil, err diff --git a/internal/pkg/process/ptrace/ptrace_linux.go b/internal/pkg/process/ptrace/ptrace_linux.go index 4660560d0..aeabb6bd3 100644 --- a/internal/pkg/process/ptrace/ptrace_linux.go +++ b/internal/pkg/process/ptrace/ptrace_linux.go @@ -24,6 +24,7 @@ import ( "github.com/go-logr/logr" "github.com/hashicorp/go-version" "github.com/pkg/errors" + "go.opentelemetry.io/auto/internal/pkg/instrumentors/utils" "go.opentelemetry.io/auto/internal/pkg/log" ) @@ -31,8 +32,10 @@ import ( const waitPidErrorMessage = "waitpid ret value: %d" const ( - MADV_POPULATE_READ = 0x16 - MADV_POPULATE_WRITE = 0x17 + // MADV_POPULATE_READ. + MadvisePopulateRead = 0x16 + // MADV_POPULATE_WRITE. + MadvisePopulateWrite = 0x17 ) var threadRetryLimit = 10 @@ -229,7 +232,7 @@ func (p *TracedProgram) Madvise(addr uint64, length uint64) error { minVersion := version.Must(version.NewVersion("5.14")) log.Logger.V(0).Info("Detected linux kernel version", "version", ver) if ver.GreaterThanOrEqual(minVersion) { - advice = syscall.MADV_WILLNEED | MADV_POPULATE_WRITE | MADV_POPULATE_READ + advice = syscall.MADV_WILLNEED | MadvisePopulateRead | MadvisePopulateWrite } _, err = p.Syscall(syscall.SYS_MADVISE, addr, length, advice, 0, 0, 0) From c73064d0e756fa7873f30f1f11ebc760ae758213 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 11 Oct 2023 12:08:31 +0300 Subject: [PATCH 63/67] Add error handling to avoid multiple map entries for the same uprobe --- .../bpf/google.golang.org/grpc/bpf/probe.bpf.c | 18 ++++++++++++++---- .../grpc/server/bpf/probe.bpf.c | 17 +++++++++++++---- .../bpf/net/http/client/bpf/probe.bpf.c | 6 +++++- .../bpf/net/http/server/bpf/probe.bpf.c | 2 +- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c index e9fa07573..df33afa65 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/bpf/probe.bpf.c @@ -88,6 +88,20 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) u64 method_ptr_pos = 4; u64 method_len_pos = 5; + void *context_ptr = get_Go_context(ctx, 3, 0, true); + if (context_ptr == NULL) + { + return 0; + } + // Get key + void *key = get_consistent_key(ctx, context_ptr); + void *grpcReq_ptr = bpf_map_lookup_elem(&grpc_events, &key); + if (grpcReq_ptr != NULL) + { + bpf_printk("uprobe/ClientConn_Invoke already tracked with the current context"); + return 0; + } + struct grpc_request_t grpcReq = {}; grpcReq.start_time = bpf_ktime_get_ns(); @@ -107,7 +121,6 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) } // Get parent if exists - void *context_ptr = get_Go_context(ctx, 3, 0, true); struct span_context *parent_span_ctx = get_parent_span_context(context_ptr); if (parent_span_ctx != NULL) { @@ -120,9 +133,6 @@ int uprobe_ClientConn_Invoke(struct pt_regs *ctx) grpcReq.sc = generate_span_context(); } - // Get key - void *key = get_consistent_key(ctx, context_ptr); - // Write event bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); start_tracking_span(context_ptr, &grpcReq.sc); diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 3f3876968..40d88ea3a 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -75,6 +75,19 @@ int uprobe_server_handleStream(struct pt_regs *ctx) { u64 stream_pos = 4; void *stream_ptr = get_argument(ctx, stream_pos); + // Get key + void *ctx_iface = get_Go_context(ctx, 4, stream_ctx_pos, false); + if (ctx_iface == NULL) + { + return 0; + } + void *key = get_consistent_key(ctx, ctx_iface); + void *grpcReq_event_ptr = bpf_map_lookup_elem(&grpc_events, &key); + if (grpcReq_event_ptr != NULL) + { + bpf_printk("uprobe/server_handleStream already tracked with the current context"); + return 0; + } // Get parent context if exists u32 stream_id = 0; @@ -101,10 +114,6 @@ int uprobe_server_handleStream(struct pt_regs *ctx) return 0; } - // Get key - void *ctx_iface = get_Go_context(ctx, 4, stream_ctx_pos, false); - void *key = get_consistent_key(ctx, ctx_iface); - // Write event bpf_map_update_elem(&grpc_events, &key, &grpcReq, 0); start_tracking_span(ctx_iface, &grpcReq.sc); diff --git a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c index 14b4a2ec8..e94795215 100644 --- a/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/client/bpf/probe.bpf.c @@ -157,11 +157,15 @@ int uprobe_HttpClient_Do(struct pt_regs *ctx) { // Get parent if exists void *context_ptr_val = get_Go_context(ctx, 2, ctx_ptr_pos, false); + if (context_ptr_val == NULL) + { + return 0; + } void *key = get_consistent_key(ctx, context_ptr_val); void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) { - bpf_printk("client: httpReq_ptr is not null"); + bpf_printk("uprobe/HttpClient_Do already tracked with the current context"); return 0; } diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 7e90e188e..064afad48 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -184,7 +184,7 @@ int uprobe_HandlerFunc_ServeHTTP(struct pt_regs *ctx) void *httpReq_ptr = bpf_map_lookup_elem(&http_events, &key); if (httpReq_ptr != NULL) { - bpf_printk("httpReq_ptr is not null"); + bpf_printk("uprobe/HandlerFunc_ServeHTTP already tracked with the current context"); return 0; } From ca7f5eddcdf7b636bb3ac757596e3f1306849aff Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 11 Oct 2023 13:24:49 +0300 Subject: [PATCH 64/67] Improve stop_tracking_span to handle more cases --- internal/include/go_context.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 03b5be2d6..527ae09ac 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -111,6 +111,7 @@ static __always_inline void stop_tracking_span(struct span_context *sc, struct s void *parent_ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, psc); if (parent_ctx == NULL) { + // No parent span, delete the context bpf_map_delete_elem(&tracked_spans, ctx); } else { @@ -123,6 +124,10 @@ static __always_inline void stop_tracking_span(struct span_context *sc, struct s { bpf_printk("stop_tracking_span: ctx_val != parent_ctx_val"); bpf_map_delete_elem(&tracked_spans, ctx); + } else { + // Parent with the same context, update the entry to point to the parent span + bpf_printk("stop_tracking_span: ctx_val == parent_ctx_val"); + bpf_map_update_elem(&tracked_spans, ctx, psc, BPF_ANY); } } From 98010242fd0aa6d0badce1b4fdef91d2bb2eacdf Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 11 Oct 2023 14:00:26 +0300 Subject: [PATCH 65/67] increase max concurrent spans capacity for maps --- internal/include/go_context.h | 1 + internal/include/span_context.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 527ae09ac..19a285d1b 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -19,6 +19,7 @@ #include "go_types.h" #define MAX_DISTANCE 10 +#define MAX_CONCURRENT_SPANS 1000 struct { diff --git a/internal/include/span_context.h b/internal/include/span_context.h index 07e9a7858..4395b020d 100644 --- a/internal/include/span_context.h +++ b/internal/include/span_context.h @@ -18,7 +18,6 @@ #include "utils.h" #define SPAN_CONTEXT_STRING_SIZE 55 -#define MAX_CONCURRENT_SPANS 100 struct span_context { From 06116f207ac45993a547d3b7c4308b22a39d920c Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Wed, 11 Oct 2023 14:16:39 +0300 Subject: [PATCH 66/67] remove printk's --- internal/include/go_context.h | 3 +-- .../bpf/google.golang.org/grpc/server/bpf/probe.bpf.c | 1 - internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index 19a285d1b..a447c0392 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -123,11 +123,10 @@ static __always_inline void stop_tracking_span(struct span_context *sc, struct s if (ctx_val != parent_ctx_val) { - bpf_printk("stop_tracking_span: ctx_val != parent_ctx_val"); + // Parent with different context, delete the context bpf_map_delete_elem(&tracked_spans, ctx); } else { // Parent with the same context, update the entry to point to the parent span - bpf_printk("stop_tracking_span: ctx_val == parent_ctx_val"); bpf_map_update_elem(&tracked_spans, ctx, psc, BPF_ANY); } } diff --git a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c index 40d88ea3a..906b8ae7a 100644 --- a/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/google.golang.org/grpc/server/bpf/probe.bpf.c @@ -145,7 +145,6 @@ int uprobe_decodeState_decodeHeader(struct pt_regs *ctx) bpf_probe_read(current_key, sizeof(current_key), hf.name.str); if (bpf_memcmp(key, current_key, sizeof(key))) { - bpf_printk("Found traceparent header grpc"); char val[W3C_VAL_LENGTH]; bpf_probe_read(val, W3C_VAL_LENGTH, hf.value.str); diff --git a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 064afad48..43743354b 100644 --- a/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/internal/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -137,7 +137,6 @@ static __always_inline struct span_context *extract_context_from_req_headers(voi { continue; } - bpf_printk("found traceparent header in http server"); void *traceparent_header_value_ptr = map_value->values[i].array; struct go_string traceparent_header_value_go_str; res = bpf_probe_read(&traceparent_header_value_go_str, sizeof(traceparent_header_value_go_str), traceparent_header_value_ptr); From 1e996bdc2712512624cb774f7d05d97b037a4d73 Mon Sep 17 00:00:00 2001 From: Ron Federman Date: Sat, 14 Oct 2023 10:39:54 +0300 Subject: [PATCH 67/67] Fix stop_tracking_span --- internal/include/go_context.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/include/go_context.h b/internal/include/go_context.h index a447c0392..b47552a52 100644 --- a/internal/include/go_context.h +++ b/internal/include/go_context.h @@ -97,8 +97,8 @@ static __always_inline void start_tracking_span(void *contextContext, struct spa } static __always_inline void stop_tracking_span(struct span_context *sc, struct span_context *psc) { - if (psc == NULL || sc == NULL) { - bpf_printk("stop_tracking_span: psc or sc is null"); + if (sc == NULL) { + bpf_printk("stop_tracking_span: sc is null"); return; } @@ -109,7 +109,7 @@ static __always_inline void stop_tracking_span(struct span_context *sc, struct s return; } - void *parent_ctx = bpf_map_lookup_elem(&tracked_spans_by_sc, psc); + void *parent_ctx = ((psc == NULL) ? NULL : bpf_map_lookup_elem(&tracked_spans_by_sc, psc)); if (parent_ctx == NULL) { // No parent span, delete the context