Skip to content

Commit

Permalink
new(pkg/driver,cmd/driver): implemented kmod modprobe/insmod.
Browse files Browse the repository at this point in the history
Signed-off-by: Federico Di Pierro <[email protected]>
  • Loading branch information
FedeDP committed Nov 6, 2023
1 parent 493826f commit 9116f52
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 32 deletions.
23 changes: 20 additions & 3 deletions cmd/driver/prepare/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -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)
}
4 changes: 2 additions & 2 deletions pkg/driver/distro/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
16 changes: 8 additions & 8 deletions pkg/driver/distro/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,23 @@ 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)
f, err := os.Open(destination) //nolint:gosec

Check failure on line 64 in pkg/driver/distro/generic.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
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,
Expand All @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions pkg/driver/type/bpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
63 changes: 44 additions & 19 deletions pkg/driver/type/kmod.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check failure on line 67 in pkg/driver/type/kmod.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
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

Check failure on line 74 in pkg/driver/type/kmod.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
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

Check failure on line 99 in pkg/driver/type/kmod.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
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

Check failure on line 112 in pkg/driver/type/kmod.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
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

Check failure on line 128 in pkg/driver/type/kmod.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
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

Check failure on line 140 in pkg/driver/type/kmod.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
_, err := exec.Command("insmod", driverName).Output() //nolint:gosec

Check failure on line 141 in pkg/driver/type/kmod.go

View workflow job for this annotation

GitHub Actions / Lint golang files

whyNoLint: include an explanation for nolint directive (gocritic)
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"
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/driver/type/modernbpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 ""
}
Expand Down
1 change: 1 addition & 0 deletions pkg/driver/type/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit 9116f52

Please sign in to comment.