VYPR
High severity7.8NVD Advisory· Published Jan 29, 2026· Updated Apr 30, 2026

CVE-2026-24905

CVE-2026-24905

Description

Inspektor Gadget is a set of tools and framework for data collection and system inspection on Kubernetes clusters and Linux hosts using eBPF. The ig binary provides a subcommand for image building, used to generate custom gadget OCI images. A part of this functionality is implemented in the file inspektor-gadget/cmd/common/image/build.go. The Makefile.build file is the Makefile template employed during the building process. This file includes user-controlled data in an unsafe fashion, specifically some parameters are embedded without an adequate escaping in the commands inside the Makefile. Prior to version 0.48.1, this implementation is vulnerable to command injection: an attacker able to control values in the buildOptions structure would be able to execute arbitrary commands during the building process. An attacker able to exploit this vulnerability would be able to execute arbitrary command on the Linux host where the ig command is launched, if images are built with the --local flag or on the build container invoked by ig, if the --local flag is not provided. The buildOptions structure is extracted from the YAML gadget manifest passed to the ig image build command. Therefore, the attacker would need a way to control either the full build.yml file passed to the ig image build command, or one of its options. Typically, this could happen in a CI/CD scenario that builds untrusted gadgets to verify correctness. Version 0.51.1 fixes the issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/inspektor-gadget/inspektor-gadgetGo
< 0.51.10.51.1

Affected products

1

Patches

2
d9bf2fe4a180

cmd: Convert Makefile.build to golang.

5 files changed · +441 187
  • cmd/common/image/build.go+96 80 modified
    @@ -16,19 +16,15 @@ package image
     
     import (
     	"context"
    -	"embed"
     	"errors"
     	"fmt"
     	"os"
    -	"os/exec"
     	"path/filepath"
    -	"runtime"
     	"slices"
     	"strconv"
     	"strings"
     	"time"
     
    -	"github.com/moby/moby/api/pkg/stdcopy"
     	"github.com/moby/moby/api/types/container"
     	"github.com/moby/moby/api/types/mount"
     	"github.com/moby/moby/client"
    @@ -41,9 +37,6 @@ import (
     	"github.com/inspektor-gadget/inspektor-gadget/pkg/oci"
     )
     
    -//go:embed helpers
    -var helpersFS embed.FS
    -
     // It can be overridden at build time
     var builderImage = "ghcr.io/inspektor-gadget/gadget-builder:main"
     
    @@ -119,34 +112,82 @@ func NewBuildCmd() *cobra.Command {
     
     type buildOptions struct {
     	outputDir         string
    -	forceColorsFlag   string
     	ebpfSourcePath    string
     	wasmSourcePath    string
    -	btfgen            bool
     	btfHubArchivePath string
    -	useInTreeHeaders  string
    +	btfgen            bool
    +	forceColorsFlag   bool
    +	useInTreeHeaders  bool
    +}
    +
    +func isFlag(str string) bool {
    +	return strings.HasPrefix(str, "-")
    +}
    +
    +func isResponseFile(str string) bool {
    +	// Response file starts with @, see:
    +	// https://gcc.gnu.org/wiki/Response_Files
    +	return strings.HasPrefix(str, "@")
     }
     
    -func buildCmd(options buildOptions) []string {
    -	cmd := []string{
    -		"make", "-f", filepath.Join(options.outputDir, "Makefile.build"),
    -		"-j", fmt.Sprintf("%d", runtime.NumCPU()),
    -		"OUTPUTDIR=" + options.outputDir,
    -		"FORCE_COLORS=" + options.forceColorsFlag,
    -		"USE_IN_TREE_HEADERS=" + options.useInTreeHeaders,
    +// Ensure the string build options are path to avoid flags injection.
    +func checkBuildOptions(buildOpts buildOptions) error {
    +	for _, opt := range []string{buildOpts.outputDir, buildOpts.ebpfSourcePath, buildOpts.wasmSourcePath, buildOpts.btfHubArchivePath} {
    +		opt = strings.TrimSpace(opt)
    +		if isFlag(opt) {
    +			return fmt.Errorf("flags are not accepted: %q", opt)
    +		}
    +
    +		if isResponseFile(opt) {
    +			return fmt.Errorf("response file are not accepted: %q", opt)
    +		}
     	}
     
    -	if options.ebpfSourcePath != "" {
    -		cmd = append(cmd, "EBPFSOURCE="+options.ebpfSourcePath, "ebpf")
    +	return nil
    +}
    +
    +func buildPipeline(opts buildOptions) ([]buildStep, error) {
    +	if err := checkBuildOptions(opts); err != nil {
    +		return nil, fmt.Errorf("wrong build option detected: %w", err)
     	}
    -	if options.wasmSourcePath != "" {
    -		cmd = append(cmd, "WASM="+options.wasmSourcePath, "wasm")
    +
    +	var steps []buildStep
    +
    +	if opts.ebpfSourcePath != "" {
    +		for _, arch := range []string{oci.ArchAmd64, oci.ArchArm64} {
    +			steps = append(steps, newClangCompileStep(arch, opts))
    +		}
     	}
    -	if options.btfgen {
    -		cmd = append(cmd, "BTFHUB_ARCHIVE="+options.btfHubArchivePath, "btfgen")
    +
    +	if opts.wasmSourcePath != "" {
    +		switch {
    +		case strings.HasSuffix(opts.wasmSourcePath, ".go"):
    +			steps = append(steps, newGoBuildStep(opts))
    +		case strings.HasSuffix(opts.wasmSourcePath, ".rs"):
    +			steps = append(steps, newCargoBuildStep(opts))
    +		case strings.HasSuffix(opts.wasmSourcePath, ".wasm"):
    +			// Already compiled, nothing to do.
    +		default:
    +			return nil, fmt.Errorf("unsupported wasm file type: %s", opts.wasmSourcePath)
    +		}
     	}
     
    -	return cmd
    +	if opts.btfgen {
    +		for _, arch := range []string{oci.ArchAmd64, oci.ArchArm64} {
    +			steps = append(steps, newBtfgenStep(arch, opts))
    +		}
    +	}
    +
    +	return steps, nil
    +}
    +
    +func runPipeline(runner commandRunner, steps []buildStep) error {
    +	for _, step := range steps {
    +		if err := step.run(runner); err != nil {
    +			return err
    +		}
    +	}
    +	return nil
     }
     
     func runBuild(cmd *cobra.Command, opts *cmdOpts) error {
    @@ -254,43 +295,28 @@ func runBuild(cmd *cobra.Command, opts *cmdOpts) error {
     		return fmt.Errorf("at least one of ebpf source (program.bpf.c), metadata (gadget.yaml), .go files (present in go folder) or wasm module is required")
     	}
     
    -	// copy helper files
    -	files, err := helpersFS.ReadDir("helpers")
    -	if err != nil {
    -		return fmt.Errorf("reading helpers: %w", err)
    -	}
    -
    -	for _, file := range files {
    -		if file.IsDir() {
    -			continue
    -		}
    -
    -		data, err := helpersFS.ReadFile(filepath.Join("helpers", file.Name()))
    -		if err != nil {
    -			return fmt.Errorf("reading helper file: %w", err)
    -		}
    -
    -		if err := os.WriteFile(filepath.Join(opts.outputDir, file.Name()), data, 0o600); err != nil {
    -			return fmt.Errorf("writing helper file: %w", err)
    -		}
    -	}
    -
     	if conf.EBPFSource != "" || conf.Wasm != "" {
     		if opts.local {
    -			cmd := buildCmd(buildOptions{
    +			steps, err := buildPipeline(buildOptions{
     				outputDir:         opts.outputDir,
     				ebpfSourcePath:    conf.EBPFSource,
     				wasmSourcePath:    conf.Wasm,
     				btfHubArchivePath: opts.btfhubarchive,
     				btfgen:            opts.btfgen,
     			})
    -			command := exec.Command(cmd[0], cmd[1:]...)
    -			out, err := command.CombinedOutput()
     			if err != nil {
    -				return fmt.Errorf("build script: %w: %s", err, out)
    +				return fmt.Errorf("building build pipeline: %w", err)
     			}
    +
    +			runner := &localRunner{verbose: common.Verbose}
     			if common.Verbose {
    -				fmt.Printf("Build logs start:\n%s\nBuild logs end\n", string(out))
    +				fmt.Printf("Build logs start:\n")
    +			}
    +			if err := runPipeline(runner, steps); err != nil {
    +				return fmt.Errorf("local build: %w", err)
    +			}
    +			if common.Verbose {
    +				fmt.Printf("Build logs end\n")
     			}
     		} else {
     			if err := buildInContainer(opts, conf); err != nil {
    @@ -445,7 +471,7 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     	pathHost := cwd
     
     	inspektorGadetSrcPath := os.Getenv("IG_SOURCE_PATH")
    -	useInTreeHeaders := "false"
    +	useInTreeHeaders := false
     	if inspektorGadetSrcPath != "" {
     		pathHost = inspektorGadetSrcPath
     		// find the gadget relative path to the inspektor-gadget source
    @@ -456,7 +482,7 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     		gadgetSourcePath = filepath.Join("/work", gadgetRelativePath)
     
     		// use in-tree headers too
    -		useInTreeHeaders = "true"
    +		useInTreeHeaders = true
     	}
     
     	buildOpts := buildOptions{
    @@ -475,10 +501,13 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     	}
     
     	if term.IsTerminal(int(os.Stdout.Fd())) && term.IsTerminal(int(os.Stderr.Fd())) {
    -		buildOpts.forceColorsFlag = "true"
    +		buildOpts.forceColorsFlag = true
     	}
     
    -	cmd := buildCmd(buildOpts)
    +	steps, err := buildPipeline(buildOpts)
    +	if err != nil {
    +		return fmt.Errorf("building build pipeline: %w", err)
    +	}
     
     	// The work mount ReadOnly field is updated as false, to allow Cargo.lock to compiled in /work folder for rust source code.
     	mounts := []mount.Mount{
    @@ -508,7 +537,7 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     		client.ContainerCreateOptions{
     			Config: &container.Config{
     				Image:      opts.builderImage,
    -				Cmd:        cmd,
    +				Cmd:        []string{"sleep", "inf"},
     				WorkingDir: gadgetSourcePath,
     				User:       fmt.Sprintf("%d:%d", os.Getuid(), os.Getgid()),
     			},
    @@ -521,7 +550,7 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     		return fmt.Errorf("creating builder container: %w", err)
     	}
     	defer func() {
    -		if _, err := cli.ContainerRemove(ctx, resp.ID, client.ContainerRemoveOptions{}); err != nil {
    +		if _, err := cli.ContainerRemove(ctx, resp.ID, client.ContainerRemoveOptions{Force: true}); err != nil {
     			fmt.Printf("Failed to remove builder container: %s\n", err)
     		}
     	}()
    @@ -530,34 +559,21 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     		return fmt.Errorf("starting builder container: %w", err)
     	}
     
    -	var status container.WaitResponse
    -
    -	waitResult := cli.ContainerWait(ctx, resp.ID, client.ContainerWaitOptions{Condition: container.WaitConditionNotRunning})
    -	select {
    -	case err := <-waitResult.Error:
    -		if err != nil {
    -			return fmt.Errorf("waiting for builder container: %w", err)
    -		}
    -	case status = <-waitResult.Result:
    +	runner := &containerRunner{
    +		ctx:         ctx,
    +		cli:         cli,
    +		containerID: resp.ID,
    +		verbose:     common.Verbose,
     	}
     
    -	outputOpts := client.ContainerLogsOptions{ShowStderr: true}
    -
    -	if status.StatusCode != 0 || common.Verbose {
    -		outputOpts.ShowStdout = true
    +	if common.Verbose {
    +		fmt.Println("Build logs start:")
     	}
    -
    -	logResult, err := cli.ContainerLogs(ctx, resp.ID, outputOpts)
    -	if err != nil {
    -		return fmt.Errorf("getting builder container logs: %w", err)
    +	if err := runPipeline(runner, steps); err != nil {
    +		return fmt.Errorf("container build: %w", err)
     	}
    -
    -	fmt.Println("Build logs start:")
    -	stdcopy.StdCopy(os.Stdout, os.Stderr, logResult)
    -	fmt.Println("Build logs end")
    -
    -	if status.StatusCode != 0 {
    -		return fmt.Errorf("builder container exited with status %d", status.StatusCode)
    +	if common.Verbose {
    +		fmt.Println("Build logs end")
     	}
     
     	return nil
    
  • cmd/common/image/build-step.go+234 0 added
    @@ -0,0 +1,234 @@
    +// Copyright 2026 The Inspektor Gadget 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 image
    +
    +import (
    +	"fmt"
    +	"path/filepath"
    +	"runtime"
    +	"strings"
    +
    +	"github.com/inspektor-gadget/inspektor-gadget/pkg/oci"
    +)
    +
    +type buildStep struct {
    +	opts       buildOptions
    +	targetArch string
    +	run        func(runner commandRunner) error
    +}
    +
    +var goArchToKernelArch = map[string]string{
    +	"amd64": "x86_64",
    +	"arm64": "aarch64",
    +}
    +
    +func translateArch(arch string) string {
    +	if arch == oci.ArchAmd64 {
    +		return "x86"
    +	}
    +
    +	return arch
    +}
    +
    +func translateArchBtf(arch string) string {
    +	if arch == oci.ArchAmd64 {
    +		return "x86_64"
    +	}
    +
    +	return arch
    +}
    +
    +func newClangCompileStep(targetArch string, opts buildOptions) buildStep {
    +	clangCompileStep := buildStep{
    +		opts:       opts,
    +		targetArch: targetArch,
    +	}
    +
    +	clangCompileStep.run = func(runner commandRunner) error {
    +		bpfObjectPath := filepath.Join(clangCompileStep.opts.outputDir, fmt.Sprintf("%s.bpf.o", clangCompileStep.targetArch))
    +
    +		kernelArch, ok := goArchToKernelArch[runtime.GOARCH]
    +		if !ok {
    +			return fmt.Errorf("no kernel architecture corresponding to %q", runtime.GOARCH)
    +		}
    +
    +		cmd := []string{
    +			"clang",
    +			"-target", "bpf",
    +			"-Wall",
    +			"-g",
    +			"-O2",
    +			fmt.Sprintf("-I/usr/include/%s-linux-gnu", kernelArch),
    +			"-D", fmt.Sprintf("__TARGET_ARCH_%s", translateArch(clangCompileStep.targetArch)),
    +			"-c", clangCompileStep.opts.ebpfSourcePath,
    +			"-I", fmt.Sprintf("/usr/include/gadget/%s/", clangCompileStep.targetArch),
    +			"-o", bpfObjectPath,
    +		}
    +
    +		if clangCompileStep.opts.useInTreeHeaders {
    +			cmd = append(cmd,
    +				"-I", "/work/include/",
    +				"-I", fmt.Sprintf("/work/include/gadget/%s/", clangCompileStep.targetArch),
    +			)
    +		}
    +
    +		if _, _, err := runner.run(cmd, nil); err != nil {
    +			return fmt.Errorf("clang compile for %s: %w", clangCompileStep.targetArch, err)
    +		}
    +
    +		if _, _, err := runner.run([]string{"llvm-strip", "-g", bpfObjectPath}, nil); err != nil {
    +			return fmt.Errorf("llvm-strip for %s: %w", clangCompileStep.targetArch, err)
    +		}
    +
    +		return nil
    +	}
    +
    +	return clangCompileStep
    +}
    +
    +func newGoBuildStep(opts buildOptions) buildStep {
    +	goBuildStep := buildStep{opts: opts}
    +
    +	goBuildStep.run = func(runner commandRunner) error {
    +		cmd := []string{
    +			"go", "build",
    +			"-C", filepath.Dir(goBuildStep.opts.wasmSourcePath),
    +			"-o", filepath.Join(goBuildStep.opts.outputDir, "program.wasm"),
    +			// -buildmode=c-shared to build the wasm as a reactor module, see:
    +			// https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md#current-unstable-abi
    +			"-buildmode=c-shared",
    +			"-ldflags", "-w -s",
    +			filepath.Base(goBuildStep.opts.wasmSourcePath),
    +		}
    +		env := []string{
    +			"CGO_ENABLED=0",
    +			"GOOS=wasip1",
    +			"GOARCH=wasm",
    +		}
    +
    +		if _, _, err := runner.run(cmd, env); err != nil {
    +			return fmt.Errorf("go build wasm: %w", err)
    +		}
    +		return nil
    +	}
    +
    +	return goBuildStep
    +}
    +
    +func newCargoBuildStep(opts buildOptions) buildStep {
    +	cargoBuildStep := buildStep{opts: opts}
    +
    +	cargoBuildStep.run = func(runner commandRunner) error {
    +		cmd := []string{"cargo"}
    +		if cargoBuildStep.opts.forceColorsFlag {
    +			cmd = append(cmd, "--color", "always")
    +		}
    +		cmd = append(cmd,
    +			"build",
    +			"--target", "wasm32-wasip1", "--release",
    +			"--manifest-path", filepath.Join(filepath.Dir(cargoBuildStep.opts.wasmSourcePath), "..", "Cargo.toml"),
    +		)
    +		env := []string{fmt.Sprintf("CARGO_TARGET_DIR=%s", cargoBuildStep.opts.outputDir)}
    +
    +		if _, _, err := runner.run(cmd, env); err != nil {
    +			return fmt.Errorf("cargo build: %w", err)
    +		}
    +
    +		cargoTomlPath := filepath.Join(filepath.Dir(cargoBuildStep.opts.wasmSourcePath), "..", "Cargo.toml")
    +		awkOut, _, err := runner.run([]string{
    +			"awk", "-F", `"`, `/^name *=/ { print $2; exit }`, cargoTomlPath,
    +		}, nil)
    +		if err != nil {
    +			return fmt.Errorf("reading package name from Cargo.toml: %w", err)
    +		}
    +		packageName := strings.TrimSpace(awkOut)
    +
    +		src := filepath.Join(cargoBuildStep.opts.outputDir, "wasm32-wasip1", "release", packageName+".wasm")
    +		dst := filepath.Join(cargoBuildStep.opts.outputDir, "program.wasm")
    +		if _, _, err := runner.run([]string{"cp", src, dst}, nil); err != nil {
    +			return fmt.Errorf("copying wasm output: %w", err)
    +		}
    +
    +		return nil
    +	}
    +
    +	return cargoBuildStep
    +}
    +
    +func newBtfgenStep(targetArch string, opts buildOptions) buildStep {
    +	btfgenStep := buildStep{
    +		opts:       opts,
    +		targetArch: targetArch,
    +	}
    +
    +	btfgenStep.run = func(runner commandRunner) error {
    +		translatedArch := translateArchBtf(btfgenStep.targetArch)
    +		bpfObjectPath := filepath.Join(btfgenStep.opts.outputDir, fmt.Sprintf("%s.bpf.o", btfgenStep.targetArch))
    +		outputBtfDirPath := filepath.Join(btfgenStep.opts.outputDir, "btfs", translatedArch)
    +		btfArchivePath := filepath.Join(btfgenStep.opts.outputDir, fmt.Sprintf("btfs-%s.tar.gz", translatedArch))
    +
    +		findOut, _, err := runner.run([]string{
    +			"find", btfgenStep.opts.btfHubArchivePath,
    +			"-iregex", fmt.Sprintf(".*%s.*", translatedArch),
    +			"-type", "f",
    +			"-name", "*.btf.tar.xz",
    +		}, nil)
    +		if err != nil {
    +			return fmt.Errorf("finding btf archives for %s: %w", translatedArch, err)
    +		}
    +
    +		for _, btfArchiveFile := range strings.Split(strings.TrimSpace(findOut), "\n") {
    +			if btfArchiveFile == "" {
    +				continue
    +			}
    +
    +			btfFilePath := strings.TrimSuffix(btfArchiveFile, ".tar.xz")
    +			btfFilename := filepath.Base(btfFilePath)
    +			outputBtfFilePath := filepath.Join(outputBtfDirPath, btfFilename)
    +
    +			if _, _, err := runner.run([]string{
    +				"tar", "xfJ", btfArchiveFile,
    +				"-C", filepath.Dir(btfArchiveFile),
    +				"--touch",
    +			}, nil); err != nil {
    +				return fmt.Errorf("extracting %s: %w", btfArchiveFile, err)
    +			}
    +
    +			if _, _, err := runner.run([]string{"mkdir", "-p", outputBtfDirPath}, nil); err != nil {
    +				return fmt.Errorf("creating btf output dir: %w", err)
    +			}
    +
    +			if _, _, err := runner.run([]string{
    +				"bpftool", "gen", "min_core_btf", btfFilePath, outputBtfFilePath, bpfObjectPath,
    +			}, nil); err != nil {
    +				return fmt.Errorf("bpftool gen min_core_btf for %s: %w", btfFilePath, err)
    +			}
    +
    +			if _, _, err := runner.run([]string{"rm", "-f", btfFilePath}, nil); err != nil {
    +				return fmt.Errorf("removing %s: %w", btfFilePath, err)
    +			}
    +		}
    +
    +		if _, _, err := runner.run([]string{
    +			"tar", "czf", btfArchivePath, "-C", outputBtfDirPath, ".",
    +		}, nil); err != nil {
    +			return fmt.Errorf("creating btf archive for %s: %w", translatedArch, err)
    +		}
    +
    +		return nil
    +	}
    +
    +	return btfgenStep
    +}
    
  • cmd/common/image/cmd-runner.go+111 0 added
    @@ -0,0 +1,111 @@
    +// Copyright 2026 The Inspektor Gadget 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 image
    +
    +import (
    +	"bytes"
    +	"context"
    +	"fmt"
    +	"os"
    +	"os/exec"
    +	"strings"
    +
    +	"github.com/moby/moby/api/pkg/stdcopy"
    +	"github.com/moby/moby/client"
    +)
    +
    +type commandRunner interface {
    +	run(cmd []string, env []string) (stdout string, stderr string, err error)
    +}
    +
    +type localRunner struct {
    +	verbose bool
    +}
    +
    +func (r *localRunner) run(cmd []string, env []string) (string, string, error) {
    +	if r.verbose {
    +		fmt.Printf("%s\n", strings.Join(cmd, " "))
    +	}
    +	command := exec.Command(cmd[0], cmd[1:]...)
    +	if len(env) > 0 {
    +		command.Env = append(os.Environ(), env...)
    +	}
    +	out, err := command.CombinedOutput()
    +	if r.verbose && len(out) > 0 {
    +		fmt.Printf("%s", out)
    +	}
    +	if err != nil {
    +		return string(out), "", fmt.Errorf("running %v: %w: %s", cmd, err, out)
    +	}
    +	return string(out), "", nil
    +}
    +
    +type containerRunner struct {
    +	ctx         context.Context
    +	cli         *client.Client
    +	containerID string
    +	verbose     bool
    +}
    +
    +func (r *containerRunner) run(cmd []string, env []string) (string, string, error) {
    +	if r.verbose {
    +		fmt.Printf("%s\n", strings.Join(cmd, " "))
    +	}
    +	outBuf, errBuf, exitCode, err := execCmdInContainer(r.ctx, r.cli, r.containerID, cmd, env)
    +	if r.verbose && len(outBuf) > 0 {
    +		fmt.Printf("%s", outBuf)
    +	}
    +	if r.verbose && len(errBuf) > 0 {
    +		fmt.Printf("%s", errBuf)
    +	}
    +	if err != nil {
    +		return outBuf, errBuf, err
    +	}
    +	if exitCode != 0 {
    +		return outBuf, errBuf, fmt.Errorf("command %v exited with status %d: %s", cmd, exitCode, errBuf)
    +	}
    +	return outBuf, errBuf, nil
    +}
    +
    +func execCmdInContainer(ctx context.Context, cli *client.Client, containerID string, cmd []string, env []string) (string, string, int, error) {
    +	execCfg, err := cli.ExecCreate(ctx, containerID, client.ExecCreateOptions{
    +		Cmd:          cmd,
    +		Env:          env,
    +		AttachStdout: true,
    +		AttachStderr: true,
    +	})
    +	if err != nil {
    +		return "", "", -1, fmt.Errorf("creating container exec: %w", err)
    +	}
    +
    +	attach, err := cli.ExecAttach(ctx, execCfg.ID, client.ExecAttachOptions{})
    +	if err != nil {
    +		return "", "", -1, fmt.Errorf("attaching exec to container: %w", err)
    +	}
    +	defer attach.Close()
    +
    +	var outBuf, errBuf bytes.Buffer
    +	_, err = stdcopy.StdCopy(&outBuf, &errBuf, attach.Reader)
    +	if err != nil {
    +		return "", "", -1, fmt.Errorf("copying exec output: %w", err)
    +	}
    +
    +	inspect, err := cli.ExecInspect(ctx, execCfg.ID, client.ExecInspectOptions{})
    +	if err != nil {
    +		return outBuf.String(), errBuf.String(), -1, fmt.Errorf("inspecting exec: %w", err)
    +	}
    +
    +	return outBuf.String(), errBuf.String(), inspect.ExitCode, nil
    +}
    
  • cmd/common/image/helpers/Makefile.build+0 75 removed
    @@ -1,75 +0,0 @@
    -# This makefile is used by the build command, don't execute it manually
    -
    -CLANG ?= clang
    -LLVM_STRIP ?= llvm-strip
    -# We need <asm/types.h> and depending on Linux distributions, it is installed
    -# at different paths:
    -#
    -# * Ubuntu, package linux-libc-dev:
    -#   /usr/include/x86_64-linux-gnu/asm/types.h
    -#
    -# * Fedora, package kernel-headers
    -#   /usr/include/asm/types.h
    -#
    -# Since Ubuntu does not install it in a standard path, add a compiler flag for
    -# it.
    -BASECFLAGS = -target bpf -Wall -g -O2 -I/usr/include/$(shell uname -m)-linux-gnu
    -OUTPUTDIR ?= /tmp
    -EBPFSOURCE ?= program.bpf.c
    -CARGOFLAGS =
    -INCLUDEFLAGS =
    -FORCE_COLORS ?= false
    -USE_IN_TREE_HEADERS ?= false
    -
    -ifeq ($(FORCE_COLORS), true)
    -    CARGOFLAGS += --color always
    -endif
    -
    -ifeq ($(USE_IN_TREE_HEADERS), true)
    -    INCLUDEFLAGS += -I /work/include/ -I /work/include/gadget/@ARCH@/
    -endif
    -
    -ARCHS = amd64 arm64
    -TARGETS = $(foreach ARCH,$(ARCHS),$(OUTPUTDIR)/$(ARCH).bpf.o)
    -
    -.PHONY: ebpf
    -ebpf: $(TARGETS)
    -
    -$(OUTPUTDIR)/%.bpf.o: $(EBPFSOURCE)
    -	$(CLANG) $(BASECFLAGS) $(subst @ARCH@,$*,$(INCLUDEFLAGS)) -D __TARGET_ARCH_$(subst amd64,x86,$*) \
    -		-c $< -I /usr/include/gadget/$*/ -o $@
    -	$(LLVM_STRIP) -g $@
    -
    -.PHONY: wasm
    -ifeq ($(WASM),)
    -wasm:
    -	# No wasm file found. Nothing to do.
    -else ifeq (go,$(patsubst %.go,go,$(WASM)))
    -wasm: $(WASM)
    -	# -buildmode=c-shared to build the wasm as a reactor module. See https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md#current-unstable-abi
    -	cd $(dir $(WASM)) && \
    -	CGO_ENABLED=0 GOOS=wasip1 GOARCH=wasm go build -o $(OUTPUTDIR)/program.wasm -buildmode=c-shared -ldflags "-w -s" $(notdir $(WASM))
    -else ifeq (rs, $(patsubst %.rs,rs,$(WASM)))
    -wasm: $(WASM)
    -	cd $(dir $(WASM)) && \
    -	CARGO_TARGET_DIR=$(OUTPUTDIR) cargo $(CARGOFLAGS) build --target wasm32-wasip1 --release && \
    -	PACKAGE_NAME=$(shell awk -F\" '/^name *=/ { print $$2; exit }' $(dir $(WASM))/../Cargo.toml) && \
    -	cp $(OUTPUTDIR)/wasm32-wasip1/release/$$PACKAGE_NAME.wasm $(OUTPUTDIR)/program.wasm && \
    -	cd /work
    -else ifeq (wasm,$(patsubst %.wasm,wasm,$(WASM)))
    -wasm:
    -	# Wasm file already compiled. Nothing to do.
    -else
    -wasm:
    -	$(error Unsupported wasm file type: $(notdir $(WASM)))
    -endif
    -
    -# Get value of -f parameter
    -ALT_MAKEFILE := $(lastword $(MAKEFILE_LIST))
    -MAKEFILE_DIR := $(dir $(ALT_MAKEFILE))
    -
    -.PHONY: btfgen
    -btfgen: $(foreach ARCH,$(ARCHS),btfgen-$(ARCH))
    -
    -btfgen-%: $(OUTPUTDIR)/%.bpf.o
    -	$(MAKE) -f $(MAKEFILE_DIR)/Makefile.build.btfgen BPF_OBJECT=$^ ARCH=$(subst amd64,x86_64,$*) btfs; \
    
  • cmd/common/image/helpers/Makefile.build.btfgen+0 32 removed
    @@ -1,32 +0,0 @@
    -# This makefile is used by the build command, don't execute it manually
    -
    -BPFTOOL ?= bpftool
    -
    -ifndef BTFHUB_ARCHIVE
    -$(error BTFHUB_ARCHIVE is undefined)
    -endif
    -
    -ifndef BPF_OBJECT
    -$(error BPF_OBJECT is undefined)
    -endif
    -
    -SOURCE_BTF_FILES = $(shell find $(BTFHUB_ARCHIVE)/ -iregex ".*$(ARCH).*" -type f -name '*.btf.tar.xz')
    -MIN_CORE_BTF_FILES = $(patsubst $(BTFHUB_ARCHIVE)/%.btf.tar.xz, $(OUTPUTDIR)/btfs/$(ARCH)/%.btf, $(SOURCE_BTF_FILES))
    -
    -.PHONY: btfs
    -btfs: $(OUTPUTDIR)/btfs-$(ARCH).tar.gz
    -
    -$(MIN_CORE_BTF_FILES): $(BPF_OBJECT)
    -
    -$(OUTPUTDIR)/btfs/$(ARCH)/%.btf: BTF_FILE = $(<:.tar.xz=)
    -$(OUTPUTDIR)/btfs/$(ARCH)/%.btf: $(BTFHUB_ARCHIVE)/%.btf.tar.xz
    -	tar xvfJ $< -C "$(dir $<)" --touch > /dev/null
    -	mkdir -p "$(@D)"
    -	if [ -f $(BTF_FILE) ]; then \
    -		$(BPFTOOL) gen min_core_btf $(BTF_FILE) $@ $(BPF_OBJECT) && rm -fr $(BTF_FILE); \
    -	else \
    -		echo "$(BTF_FILE) does not exist!" >&2; \
    -	fi
    -
    -$(OUTPUTDIR)/btfs-$(ARCH).tar.gz: $(MIN_CORE_BTF_FILES)
    -	cd $(OUTPUTDIR)/btfs/$(ARCH)/ && tar c --gz -f $@ *
    
7c83ad84ff7a

cmd: Remove possibility to customize CFLAGS from build.yaml.

4 files changed · +17 25
  • cmd/common/image/build.go+5 10 modified
    @@ -59,7 +59,6 @@ type buildFile struct {
     	EBPFSource string `yaml:"ebpfsource"`
     	Wasm       string `yaml:"wasm"`
     	Metadata   string `yaml:"metadata"`
    -	CFlags     string `yaml:"cflags"`
     }
     
     type cmdOpts struct {
    @@ -122,21 +121,21 @@ func NewBuildCmd() *cobra.Command {
     
     type buildOptions struct {
     	outputDir         string
    -	cFlags            string
     	forceColorsFlag   string
     	ebpfSourcePath    string
     	wasmSourcePath    string
     	btfgen            bool
     	btfHubArchivePath string
    +	useInTreeHeaders  string
     }
     
     func buildCmd(options buildOptions) []string {
     	cmd := []string{
     		"make", "-f", filepath.Join(options.outputDir, "Makefile.build"),
     		"-j", fmt.Sprintf("%d", runtime.NumCPU()),
     		"OUTPUTDIR=" + options.outputDir,
    -		"CFLAGS=" + options.cFlags,
     		"FORCE_COLORS=" + options.forceColorsFlag,
    +		"USE_IN_TREE_HEADERS=" + options.useInTreeHeaders,
     	}
     
     	if options.ebpfSourcePath != "" {
    @@ -284,7 +283,6 @@ func runBuild(cmd *cobra.Command, opts *cmdOpts) error {
     				outputDir:         opts.outputDir,
     				ebpfSourcePath:    conf.EBPFSource,
     				wasmSourcePath:    conf.Wasm,
    -				cFlags:            conf.CFlags,
     				btfHubArchivePath: opts.btfhubarchive,
     				btfgen:            opts.btfgen,
     			})
    @@ -450,6 +448,7 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     	pathHost := cwd
     
     	inspektorGadetSrcPath := os.Getenv("IG_SOURCE_PATH")
    +	useInTreeHeaders := "false"
     	if inspektorGadetSrcPath != "" {
     		pathHost = inspektorGadetSrcPath
     		// find the gadget relative path to the inspektor-gadget source
    @@ -460,14 +459,14 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     		gadgetSourcePath = filepath.Join("/work", gadgetRelativePath)
     
     		// use in-tree headers too
    -		conf.CFlags += " -I /work/include/ -I /work/include/gadget/@ARCH@/ "
    +		useInTreeHeaders = "true"
     	}
     
     	buildOpts := buildOptions{
     		outputDir:         "/out",
    -		cFlags:            conf.CFlags,
     		btfgen:            opts.btfgen,
     		btfHubArchivePath: "/btfhub-archive",
    +		useInTreeHeaders:  useInTreeHeaders,
     	}
     
     	if conf.Wasm != "" {
    @@ -478,10 +477,6 @@ func buildInContainer(opts *cmdOpts, conf *buildFile) error {
     		buildOpts.ebpfSourcePath = filepath.Join(gadgetSourcePath, conf.EBPFSource)
     	}
     
    -	if cflags, set := os.LookupEnv("CFLAGS"); set {
    -		buildOpts.cFlags += " " + cflags
    -	}
    -
     	if term.IsTerminal(int(os.Stdout.Fd())) && term.IsTerminal(int(os.Stderr.Fd())) {
     		buildOpts.forceColorsFlag = "true"
     	}
    
  • cmd/common/image/helpers/Makefile.build+8 3 modified
    @@ -14,24 +14,29 @@ LLVM_STRIP ?= llvm-strip
     # Since Ubuntu does not install it in a standard path, add a compiler flag for
     # it.
     BASECFLAGS = -target bpf -Wall -g -O2 -I/usr/include/$(shell uname -m)-linux-gnu
    -CFLAGS ?=
     OUTPUTDIR ?= /tmp
     EBPFSOURCE ?= program.bpf.c
    -CARGOFLAGS ?=
    +CARGOFLAGS =
    +INCLUDEFLAGS =
     FORCE_COLORS ?= false
    +USE_IN_TREE_HEADERS ?= false
     
     ifeq ($(FORCE_COLORS), true)
         CARGOFLAGS += --color always
     endif
     
    +ifeq ($(USE_IN_TREE_HEADERS), true)
    +    INCLUDEFLAGS += -I /work/include/ -I /work/include/gadget/@ARCH@/
    +endif
    +
     ARCHS = amd64 arm64
     TARGETS = $(foreach ARCH,$(ARCHS),$(OUTPUTDIR)/$(ARCH).bpf.o)
     
     .PHONY: ebpf
     ebpf: $(TARGETS)
     
     $(OUTPUTDIR)/%.bpf.o: $(EBPFSOURCE)
    -	$(CLANG) $(BASECFLAGS) $(subst @ARCH@,$*,$(CFLAGS)) -D __TARGET_ARCH_$(subst amd64,x86,$*) \
    +	$(CLANG) $(BASECFLAGS) $(subst @ARCH@,$*,$(INCLUDEFLAGS)) -D __TARGET_ARCH_$(subst amd64,x86,$*) \
     		-c $< -I /usr/include/gadget/$*/ -o $@
     	$(LLVM_STRIP) -g $@
     
    
  • gadgets/traceloop/build.yaml+0 4 modified
    @@ -1,5 +1 @@
     wasm: go/program.go
    -# To print debug messages:
    -# cflags: '-DSHOW_DEBUG'
    -# To print error messages:
    -# cflags: '-DSHOW_ERROR'
    
  • gadgets/traceloop/program.bpf.c+4 8 modified
    @@ -107,10 +107,8 @@ struct remembered_args {
     #error "Traceloop is not supported on your architecture."
     #endif
     
    -/*
    - * Add the following in build.yaml to print debug messages:
    - *  cflags: '-DSHOW_DEBUG'
    - */
    +/* Uncomment the following line to show debug messages. */
    +/* #define SHOW_DEBUG */
     #if defined(SHOW_DEBUG)
     #define bpf_debug_printk(fmt, ...) bpf_printk(fmt, ##__VA_ARGS__)
     #else /* !defined(SHOW_DEBUG) */
    @@ -119,10 +117,8 @@ struct remembered_args {
     	} while (0)
     #endif /* !defined(SHOW_DEBUG) */
     
    -/*
    - * Add the following in build.yaml to print error messages:
    - *  cflags: '-DSHOW_ERROR'
    - */
    +/* Uncomment the following line to show errors. */
    +/* #define SHOW_ERROR */
     #if defined(SHOW_ERROR)
     #define bpf_error_printk(fmt, ...) bpf_printk(fmt, ##__VA_ARGS__)
     #else /* !defined(SHOW_ERROR) */
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.