Skip to content

Commit

Permalink
new(pkg): use new driverkit local build processor instead of implemen…
Browse files Browse the repository at this point in the history
…ting drivers build.

Bumped driverkit to a development version.

Signed-off-by: Federico Di Pierro <[email protected]>
  • Loading branch information
FedeDP committed Feb 14, 2024
1 parent 43f1d3c commit c7fd29a
Show file tree
Hide file tree
Showing 7 changed files with 432 additions and 395 deletions.
186 changes: 119 additions & 67 deletions go.mod

Large diffs are not rendered by default.

441 changes: 273 additions & 168 deletions go.sum

Large diffs are not rendered by default.

43 changes: 27 additions & 16 deletions pkg/driver/distro/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"strings"

"github.com/docker/docker/pkg/homedir"
"github.com/falcosecurity/driverkit/cmd"
"github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"
"gopkg.in/ini.v1"
Expand Down Expand Up @@ -168,29 +170,38 @@ func Build(ctx context.Context,
driverType drivertype.DriverType,
driverVer string,
) (string, error) {
printer.Logger.Info("Trying to compile the requested driver")
driverFileName := toFilename(d, &kr, driverName, driverType)
destination := toLocalPath(driverVer, driverFileName, kr.Architecture.ToNonDeb())
if exist, _ := utils.FileExists(destination); exist {
return destination, ErrAlreadyPresent
destPath := toLocalPath(driverVer, driverFileName, kr.Architecture.ToNonDeb())
if exist, _ := utils.FileExists(destPath); exist {
return destPath, ErrAlreadyPresent
}

env, err := d.customizeBuild(ctx, printer, driverType, kr)
if err != nil {
return "", err
}
path, err := driverType.Build(ctx, printer, kr, driverName, driverVer, env)
if err != nil {
return "", err
}
// Copy the path to the expected location.
// NOTE: for kmod, this is not useful since the driver will
// be loaded directly by dkms.
printer.Logger.Info("Copying built driver to its destination.", printer.Logger.Args("src", path, "dst", destination))
f, err := os.Open(filepath.Clean(path))
if err != nil {
return "", err
}
return destination, copyDataToLocalPath(destination, f)

srcPath := fmt.Sprintf("/usr/src/%s-%s", driverName, driverVer)

fixedKr := d.FixupKernel(kr)
ro := cmd.NewRootOptions()
ro.Architecture = fixedKr.Architecture.String()
ro.DriverVersion = driverVer
ro.KernelVersion = fixedKr.KernelVersion
ro.ModuleDriverName = driverName
ro.ModuleDeviceName = driverName
ro.KernelRelease = fixedKr.String()
ro.Target = "local"
ro.Output = driverType.ToOutput(destPath)
// This should never happen since both kmod and bpf implement ToOutput;
// the only case this can happen is if a Build is requested for modern-bpf driver type.
// But "install" cmd is smart enough to avoid that situation.
if ro.Output.Module == "" && ro.Output.Probe == "" {
return "", errors.New("driver build without outputs attempted")
}
err = driverbuilder.NewLocalBuildProcessor(1000, true, srcPath, env).Start(ro.ToBuild())
return destPath, err
}

// Download will try to download drivers for a distro trying specified repos.
Expand Down
50 changes: 4 additions & 46 deletions pkg/driver/type/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,11 @@ package drivertype
import (
"fmt"
"os"
"os/exec"
"path/filepath"

"github.com/docker/docker/pkg/homedir"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"
"k8s.io/utils/mount"
"github.com/falcosecurity/driverkit/cmd"

"github.com/falcosecurity/falcoctl/internal/utils"
"github.com/falcosecurity/falcoctl/pkg/output"
)

Expand Down Expand Up @@ -73,46 +69,8 @@ func (b *bpf) HasArtifacts() bool {
return true
}

//nolint:gocritic // the method shall not be able to modify kr
func (b *bpf) Build(ctx context.Context,
printer *output.Printer,
_ kernelrelease.KernelRelease,
driverName, driverVersion string,
env map[string]string,
) (string, error) {
// We don't fail if this fails; let's try to build a probe anyway.
_ = mountKernelDebug(printer)
srcPath := fmt.Sprintf("/usr/src/%s-%s/bpf", driverName, driverVersion)

makeCmdArgs := fmt.Sprintf(`make -C %q`, filepath.Clean(srcPath))
makeCmd := exec.CommandContext(ctx, "bash", "-c", makeCmdArgs) //nolint:gosec // false positive
// Append requested env variables to the command env
makeCmd.Env = os.Environ()
for key, val := range env {
makeCmd.Env = append(makeCmd.Env, fmt.Sprintf("%s=%s", key, val))
}
out, err := makeCmd.CombinedOutput()
if err != nil {
printer.DefaultText.Print(string(out))
}
outProbe := fmt.Sprintf("%s/probe.o", srcPath)
return outProbe, err
}

func mountKernelDebug(printer *output.Printer) error {
// Mount /sys/kernel/debug that is needed on old (pre 4.17) kernel releases,
// since these releases still did not support raw tracepoints.
// BPF_PROG_TYPE_RAW_TRACEPOINT was introduced in 4.17 indeed:
// https://github.com/torvalds/linux/commit/c4f6699dfcb8558d138fe838f741b2c10f416cf9
exists, _ := utils.FileExists("/sys/kernel/debug/tracing")
if exists {
return nil
}
printer.Logger.Info("Mounting debugfs for bpf driver.")
mounter := mount.New("/bin/mount")
err := mounter.Mount("debugfs", "/sys/kernel/debug", "debugfs", []string{"nodev"})
if err != nil {
printer.Logger.Warn("Failed to mount debugfs.", printer.Logger.Args("err", err))
func (b *bpf) ToOutput(destPath string) cmd.OutputOptions {
return cmd.OutputOptions{
Probe: destPath,
}
return err
}
93 changes: 4 additions & 89 deletions pkg/driver/type/kmod.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@ import (
"bufio"
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"

"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"
"github.com/falcosecurity/driverkit/cmd"

"github.com/falcosecurity/falcoctl/pkg/output"
)
Expand Down Expand Up @@ -165,90 +162,8 @@ func (k *kmod) HasArtifacts() bool {
return true
}

func createDKMSMakeFile(gcc string) error {
file, err := os.OpenFile("/tmp/falco-dkms-make", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o777) //nolint:gosec // we need the file to be executable
if err != nil {
return err
}
defer file.Close()

_, err = fmt.Fprintln(file, "#!/usr/bin/env bash")
if err == nil {
_, err = fmt.Fprintln(file, `make CC=`+gcc+` $@`)
}
return err
}

//nolint:gocritic // the method shall not be able to modify kr
func (k *kmod) Build(ctx context.Context,
printer *output.Printer,
kr kernelrelease.KernelRelease,
driverName, driverVersion string,
_ map[string]string,
) (string, error) {
// Skip dkms on UEK hosts because it will always fail
if strings.Contains(kr.String(), "uek") {
printer.Logger.Warn("Skipping because the dkms install always fail (on UEK hosts).")
return "", fmt.Errorf("unsupported on uek hosts")
}

out, err := exec.Command("which", "gcc").Output()
if err != nil {
return "", err
}
gccDir := filepath.Dir(string(out))

gccs, err := filepath.Glob(gccDir + "/gcc*")
if err != nil {
return "", err
}

for _, gcc := range gccs {
// Filter away gcc-{ar,nm,...}
// Only gcc compiler has `-print-search-dirs` option.
gccSearchArgs := fmt.Sprintf(`%s -print-search-dirs 2>&1 | grep "install:"`, gcc)
_, err = exec.Command("bash", "-c", gccSearchArgs).Output() //nolint:gosec // false positive
if err != nil {
continue
}

printer.Logger.Info("Trying to dkms install module.", printer.Logger.Args("gcc", gcc))
err = createDKMSMakeFile(gcc)
if err != nil {
printer.Logger.Warn("Could not fill /tmp/falco-dkms-make content.")
continue
}
dkmsCmdArgs := fmt.Sprintf(`dkms install --directive="MAKE='/tmp/falco-dkms-make'" -m %q -v %q -k %q --verbose`,
driverName, driverVersion, kr.String())

// Try the build through dkms
out, err = exec.CommandContext(ctx, "bash", "-c", dkmsCmdArgs).CombinedOutput() //nolint:gosec // false positive
if err == nil {
koGlob := fmt.Sprintf("/var/lib/dkms/%s/%s/%s/%s/module/%s", driverName, driverVersion, kr.String(), kr.Architecture.ToNonDeb(), driverName)
var koFiles []string
koFiles, err = filepath.Glob(koGlob + ".*")
if err != nil || len(koFiles) == 0 {
printer.Logger.Warn("Module file not found.")
continue
}
koFile := koFiles[0]
printer.Logger.Info("Module installed in dkms.", printer.Logger.Args("file", koFile))
return koFile, nil
}
printer.DefaultText.Print(string(out))
dkmsLogFile := fmt.Sprintf("/var/lib/dkms/$%s/%s/build/make.log", driverName, driverVersion)
logs, err := os.ReadFile(filepath.Clean(dkmsLogFile))
if err != nil {
printer.Logger.Warn("Running dkms build failed, couldn't find dkms log", printer.Logger.Args("file", dkmsLogFile))
} else {
printer.Logger.Warn("Running dkms build failed. Dumping dkms log.", printer.Logger.Args("file", dkmsLogFile))
logBuf := bytes.NewBuffer(logs)
scanner := bufio.NewScanner(logBuf)
for scanner.Scan() {
m := scanner.Text()
printer.DefaultText.Println(m)
}
}
func (k *kmod) ToOutput(destPath string) cmd.OutputOptions {
return cmd.OutputOptions{
Module: destPath,
}
return "", fmt.Errorf("failed to compile the module")
}
8 changes: 3 additions & 5 deletions pkg/driver/type/modernbpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
package drivertype

import (
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"
"github.com/falcosecurity/driverkit/cmd"

"github.com/falcosecurity/falcoctl/pkg/output"
)
Expand Down Expand Up @@ -51,7 +50,6 @@ func (m *modernBpf) HasArtifacts() bool {
return false
}

//nolint:gocritic // the method shall not be able to modify kr
func (m *modernBpf) Build(_ context.Context, _ *output.Printer, _ kernelrelease.KernelRelease, _, _ string, _ map[string]string) (string, error) {
return "", nil
func (m *modernBpf) ToOutput(_ string) cmd.OutputOptions {
return cmd.OutputOptions{}
}
6 changes: 2 additions & 4 deletions pkg/driver/type/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ package drivertype
import (
"fmt"

"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"golang.org/x/net/context"
"github.com/falcosecurity/driverkit/cmd"

"github.com/falcosecurity/falcoctl/pkg/output"
)
Expand All @@ -37,8 +36,7 @@ type DriverType interface {
Load(printer *output.Printer, src, driverName string, fallback bool) error
Extension() string
HasArtifacts() bool
Build(ctx context.Context, printer *output.Printer, kr kernelrelease.KernelRelease,
driverName, driverVersion string, env map[string]string) (string, error)
ToOutput(destPath string) cmd.OutputOptions
}

// GetTypes return the list of supported driver types.
Expand Down

0 comments on commit c7fd29a

Please sign in to comment.