diff --git a/cmd/driver/prepare/prepare.go b/cmd/driver/prepare/prepare.go index 1297a808..5472b3b5 100644 --- a/cmd/driver/prepare/prepare.go +++ b/cmd/driver/prepare/prepare.go @@ -86,6 +86,7 @@ func (o *driverPrepareOptions) RunDriverPrepare(_ context.Context, _ []string) e o.Printer.Logger.Info("Running falcoctl driver prepare", o.Printer.Logger.Args( "driver version", o.DriverVersion, "driver type", driver.Type, + "driver name", o.Name, "arch", info.Architecture, "kernel release", info.KernelRelease, "kernel version", info.KernelVersion)) @@ -111,12 +112,15 @@ func (o *driverPrepareOptions) RunDriverPrepare(_ context.Context, _ []string) e return err } + var dest string if o.Download { // Fixup kernel information before attempting to download downloadInfo := d.FixupKernel(info) - err = d.Download(downloadInfo, o.Driver, driver.Type, o.DriverVersion, o.DriverRepos) + dest, err = d.Download(downloadInfo, o.Driver, driver.Type, o.DriverVersion, o.DriverRepos) if err == nil { + // We don't care about errors at this stage + _ = driver.Type.Load(o.Printer, dest, false) return nil } // Print the error but go on @@ -125,7 +129,20 @@ func (o *driverPrepareOptions) RunDriverPrepare(_ context.Context, _ []string) e } if o.Build { - err = d.Build() + dest, err = d.Build() + if err == nil { + // We don't care about errors + _ = driver.Type.Load(o.Printer, dest, false) + } + } + + if err != nil { + o.Printer.Logger.Error(err.Error()) + // Fallback: try to load any available driver. + // It is only useful for kmod, as it will try to + // modprobe a pre-existent version of the driver, + // hoping it will be compatible. + _ = driver.Type.Load(o.Printer, o.Name, true) } - return err + return fmt.Errorf("last error: %w", err) } diff --git a/pkg/driver/distro/distro.go b/pkg/driver/distro/distro.go index 53e3af3c..9d4068af 100644 --- a/pkg/driver/distro/distro.go +++ b/pkg/driver/distro/distro.go @@ -43,8 +43,8 @@ type Distro interface { init(printer *output.Printer, id string, cfg *ini.File) error // private GetTargetID(i driverkernel.Info) string FixupKernel(i driverkernel.Info) driverkernel.Info - Download(i driverkernel.Info, opts *options.Driver, driverType drivertype.DriverType, driverVer string, repos []string) error - Build() error + Download(i driverkernel.Info, opts *options.Driver, driverType drivertype.DriverType, driverVer string, repos []string) (string, error) + Build() (string, error) PreferredDriver(i driverkernel.Info) drivertype.DriverType } diff --git a/pkg/driver/distro/generic.go b/pkg/driver/distro/generic.go index 4a9c73ab..7ee1e754 100644 --- a/pkg/driver/distro/generic.go +++ b/pkg/driver/distro/generic.go @@ -49,15 +49,15 @@ func (g *generic) FixupKernel(i driverkernel.Info) driverkernel.Info { return i } -func (g *generic) Build() error { +func (g *generic) Build() (string, error) { // TODO compile // flatcar specific: flatcar_relocate_tools // cos specific... // minikube specific... - return fmt.Errorf("build unimplemented") + return "", fmt.Errorf("build unimplemented") } -func (g *generic) Download(i driverkernel.Info, opts *options.Driver, driverType drivertype.DriverType, driverVer string, repos []string) error { +func (g *generic) Download(i driverkernel.Info, opts *options.Driver, driverType drivertype.DriverType, driverVer string, repos []string) (string, error) { // Skip if existent driverFileName := g.toFilename(i, opts, driverType) destination := fmt.Sprintf("%s/.falco/%s/%s/%s", homedir.Get(), driverVer, i.Architecture, driverFileName) @@ -65,7 +65,7 @@ func (g *generic) Download(i driverkernel.Info, opts *options.Driver, driverType if err == nil { _ = f.Close() g.printer.Logger.Info("Skipping download, driver already present.", g.printer.Logger.Args("path", destination)) - return nil + return destination, nil } // Try to download from any specified repository, @@ -81,16 +81,16 @@ func (g *generic) Download(i driverkernel.Info, opts *options.Driver, driverType out, err := os.Create(destination) //nolint:gosec if err != nil { - return err + return destination, err } _, err = io.Copy(out, resp.Body) if err != nil { - return err + return destination, err } _ = resp.Body.Close() - return nil + return destination, nil } - return fmt.Errorf("unable to find a prebuilt %s driver", opts.Name) + return destination, fmt.Errorf("unable to find a prebuilt %s driver", opts.Name) } func (g *generic) PreferredDriver(_ driverkernel.Info) drivertype.DriverType { diff --git a/pkg/driver/type/bpf.go b/pkg/driver/type/bpf.go index 2f903ed0..21d7b5a3 100644 --- a/pkg/driver/type/bpf.go +++ b/pkg/driver/type/bpf.go @@ -41,6 +41,10 @@ func (b *bpf) Prepare(printer *output.Printer, _ string) error { return mounter.Mount("debugfs", "/sys/kernel/debug", "debugfs", []string{"nodev"}) } +func (b *bpf) Load(_ *output.Printer, _ string, _ bool) error { + return nil +} + func (b *bpf) Extension() string { return ".o" } diff --git a/pkg/driver/type/kmod.go b/pkg/driver/type/kmod.go index efc19bc8..fded6cdc 100644 --- a/pkg/driver/type/kmod.go +++ b/pkg/driver/type/kmod.go @@ -62,66 +62,91 @@ func (k *kmod) Prepare(printer *output.Printer, driverName string) error { } kmodName := strings.ReplaceAll(driverName, "-", "_") - args := printer.Logger.Args("kmod", kmodName) - - printer.Logger.Info("Check if kernel module is still loaded.", args) + printer.Logger.Info("Check if kernel module is still loaded.") lsmodCmdArgs := fmt.Sprintf(`lsmod | cut -d' ' -f1 | grep -qx %q`, kmodName) _, err = exec.Command("bash", "-c", lsmodCmdArgs).Output() //nolint:gosec if err == nil { unloaded := false // Module is still loaded, try to remove it for i := 0; i < maxRmmodWait; i++ { - printer.Logger.Info("Kernel module is still loaded.", args) - printer.Logger.Info("Trying to unload it with 'rmmod'.", args) + printer.Logger.Info("Kernel module is still loaded.") + printer.Logger.Info("Trying to unload it with 'rmmod'.") if _, err = exec.Command("rmmod", kmodName).Output(); err == nil { //nolint:gosec - printer.Logger.Info("OK! Unloading module succeeded.", args) + printer.Logger.Info("OK! Unloading module succeeded.") unloaded = true break } - printer.Logger.Info("Nothing to do...'falcoctl' will wait until you remove the kernel module to have a clean termination.", args) - printer.Logger.Info("Check that no process is using the kernel module with 'lsmod'.", args) - printer.Logger.Info("Sleep 5 seconds...", args) + printer.Logger.Info("Nothing to do...'falcoctl' will wait until you remove the kernel module to have a clean termination.") + printer.Logger.Info("Check that no process is using the kernel module with 'lsmod'.") + printer.Logger.Info("Sleep 5 seconds...") time.Sleep(rmmodWaitTime) } if !unloaded { - printer.Logger.Warn("Kernel module is still loaded, you could have incompatibility issues.", args) + printer.Logger.Warn("Kernel module is still loaded, you could have incompatibility issues.") } } else { - printer.Logger.Info("OK! There is no module loaded.", args) + printer.Logger.Info("OK! There is no module loaded.") } _, err = exec.Command("bash", "-c", "hash dkms").Output() if err != nil { - printer.Logger.Info("Skipping dkms remove (dkms not found).", args) + printer.Logger.Info("Skipping dkms remove (dkms not found).") return nil } - printer.Logger.Info("Check all versions of kernel module in dkms.", args) + printer.Logger.Info("Check all versions of kernel module in dkms.") dkmsLsCmdArgs := fmt.Sprintf(`dkms status -m %q | tr -d "," | tr -d ":" | tr "/" " " | cut -d' ' -f2`, kmodName) out, err := exec.Command("bash", "-c", dkmsLsCmdArgs).Output() //nolint:gosec if err != nil { - printer.Logger.Warn("Listing kernel module versions failed.", args, printer.Logger.Args("reason", err)) + printer.Logger.Warn("Listing kernel module versions failed.", printer.Logger.Args("reason", err)) return nil } if len(out) == 0 { - printer.Logger.Info("OK! There are no module versions in dkms.", args) + printer.Logger.Info("OK! There are no module versions in dkms.") } else { driverVersions := strings.Split(string(out), "\n") - printer.Logger.Info("There are some module versions in dkms.", args) - printer.Logger.Info("Removing all the following versions from dkms.", args, printer.Logger.Args("versions", driverVersions)) + printer.Logger.Info("There are some module versions in dkms.") + printer.Logger.Info("Removing all the following versions from dkms.", printer.Logger.Args("versions", driverVersions)) for _, dVer := range driverVersions { dkmsRmCmdArgs := fmt.Sprintf(`dkms remove -m %s -v %q --all`, kmodName, dVer) _, err = exec.Command("bash", "-c", dkmsRmCmdArgs).Output() //nolint:gosec if err == nil { - printer.Logger.Info("OK! Removing succeeded.", args, printer.Logger.Args("version", dVer)) + printer.Logger.Info("OK! Removing succeeded.", printer.Logger.Args("version", dVer)) } else { - printer.Logger.Warn("Removing failed.", args, printer.Logger.Args("version", dVer)) + printer.Logger.Warn("Removing failed.", printer.Logger.Args("version", dVer)) } } } return nil } +func (k *kmod) Load(printer *output.Printer, driverName string, fallback bool) error { + if fallback { + // Try to modprobe any existent version of the kmod; this is a fallback + // when both download and build of kmod fail. + printer.Logger.Info("Trying to load a pre existent system module, if present.") + _, err := exec.Command("modprobe", driverName).Output() //nolint:gosec + if err == nil { + printer.Logger.Info("Success: module found and loaded with modprobe.") + } else { + printer.Logger.Error("Consider compiling your own driver and loading it or getting in touch with the Falco community.") + } + return err + } + + chconCmdArgs := fmt.Sprintf(`chcon -t modules_object_t %q`, driverName) + // We don't want to catch any error from this call + // chcon(1): change file SELinux security context + _, _ = exec.Command("bash", "-c", chconCmdArgs).Output() //nolint:gosec + _, err := exec.Command("insmod", driverName).Output() //nolint:gosec + if err == nil { + printer.Logger.Info("Success: module found and loaded in dkms.") + } else { + printer.Logger.Warn("Unable to insmod module.") + } + return err +} + func (k *kmod) Extension() string { return ".ko" } diff --git a/pkg/driver/type/modernbpf.go b/pkg/driver/type/modernbpf.go index 22799c16..b88f56f5 100644 --- a/pkg/driver/type/modernbpf.go +++ b/pkg/driver/type/modernbpf.go @@ -31,6 +31,10 @@ func (m *modernBpf) Prepare(_ *output.Printer, _ string) error { return nil } +func (m *modernBpf) Load(_ *output.Printer, _ string, _ bool) error { + return nil +} + func (m *modernBpf) Extension() string { return "" } diff --git a/pkg/driver/type/type.go b/pkg/driver/type/type.go index 9f0b14b8..f873ea0f 100644 --- a/pkg/driver/type/type.go +++ b/pkg/driver/type/type.go @@ -27,6 +27,7 @@ var driverTypes = map[string]DriverType{} type DriverType interface { String() string Prepare(printer *output.Printer, driverName string) error + Load(printer *output.Printer, driverName string, fallback bool) error Extension() string HasArtifacts() bool }