diff --git a/cmd/capture.go b/cmd/capture.go index 0577435..cd8ae6a 100644 --- a/cmd/capture.go +++ b/cmd/capture.go @@ -26,6 +26,7 @@ import ( ) var functionSymbols string +var envVars []string var commandOutput bool var commandError bool var libbpfOutput bool @@ -66,7 +67,7 @@ by passing the function name symbol and the binary args. errorCh := make(chan error) ctx := context.Background() - ebpf, err := captor.InitProbes(functionSymbol, args, opts) + ebpf, err := captor.InitProbes(functionSymbol, args, envVars, opts) if err != nil { return fmt.Errorf("error setting up ebpf module: %w", err) } @@ -100,6 +101,7 @@ func init() { captureCmd.Flags().StringVarP(&functionSymbols, "functions", "f", "", "Name of the function symbols to be traced") captureCmd.MarkFlagRequired("functions") + captureCmd.Flags().StringSliceVarP(&envVars, "env-vars", "E", []string{}, "Additional environment variables to pass to the executed command") captureCmd.Flags().BoolVarP(&commandOutput, "include-cmd-stdout", "c", false, "Include the executed command output") captureCmd.Flags().BoolVarP(&commandError, "include-cmd-stderr", "e", false, "Include the executed command error") diff --git a/cmd/hunt.go b/cmd/hunt.go index 0dddd26..53fe0b0 100644 --- a/cmd/hunt.go +++ b/cmd/hunt.go @@ -84,7 +84,7 @@ var huntCmd = &cobra.Command{ errorCh := make(chan error) ctx := context.Background() - ebpf, err := captor.InitProbes(functionSymbol, captureArgs, opts) + ebpf, err := captor.InitProbes(functionSymbol, captureArgs, envVars, opts) if err != nil { return fmt.Errorf("error setting up ebpf module: %w", err) } diff --git a/internal/ebpf/probesfacade/captor/capture.go b/internal/ebpf/probesfacade/captor/capture.go index c5327b2..937a636 100644 --- a/internal/ebpf/probesfacade/captor/capture.go +++ b/internal/ebpf/probesfacade/captor/capture.go @@ -46,12 +46,13 @@ type ebpfSetup struct { lostCh chan uint64 opts CaptureOptions cmd []string + env []string } // InitProbes setup the ebpf module attaching probes and tracepoints // to the ebpf program. // Returns the ebpfSetup struct in case of seccess, an error in case of failure. -func InitProbes(functionSymbol string, cmdArgs []string, opts CaptureOptions) (*ebpfSetup, error) { +func InitProbes(functionSymbol string, cmdArgs []string, env []string, opts CaptureOptions) (*ebpfSetup, error) { if len(cmdArgs) == 0 { return nil, errors.New("error no arguments provided, at least 1 argument is required") } @@ -138,6 +139,7 @@ func InitProbes(functionSymbol string, cmdArgs []string, opts CaptureOptions) (* lostCh: lostChannel, opts: opts, cmd: cmdArgs, + env: env, }, nil } @@ -173,6 +175,7 @@ func (ebpf *ebpfSetup) Capture(ctx context.Context, resultCh chan []uint32, erro // running command to trace its syscalls go executor.Run( ebpf.cmd, + ebpf.env, ebpf.opts.CommandOutput, ebpf.opts.CommandError, &wg, diff --git a/internal/executor/exec.go b/internal/executor/exec.go index c8d42d8..530e77b 100644 --- a/internal/executor/exec.go +++ b/internal/executor/exec.go @@ -10,12 +10,18 @@ import ( // Run execute the command and wait for its end. // The cmdOutput argument is used to print the command output. -func Run(cmd []string, cmdOutput, cmdError bool, wg *sync.WaitGroup, outputCh, errorCh chan<- string) { +func Run(cmd []string, envVars []string, cmdOutput, cmdError bool, wg *sync.WaitGroup, outputCh, errorCh chan<- string) { defer func() { wg.Done() }() command := exec.Command(cmd[0], cmd[1:]...) + // assign custom env variables to the command + env := os.Environ() + if len(envVars) > 0 { + env = append(env, envVars...) + } + command.Env = env stdout, _ := command.StdoutPipe() stderr, _ := command.StderrPipe()