From 81264218b06ed0b6953db9eaeeb8fab7c9fc1e80 Mon Sep 17 00:00:00 2001 From: GLVS Kiriti Date: Wed, 20 Mar 2024 20:32:49 +0530 Subject: [PATCH 1/2] Added an event for default stable rule Linux Kernel Module Injection Signed-off-by: GLVS Kiriti --- .../syscall/linux_kernel_module_injection.go | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 events/syscall/linux_kernel_module_injection.go diff --git a/events/syscall/linux_kernel_module_injection.go b/events/syscall/linux_kernel_module_injection.go new file mode 100644 index 00000000..b9e4b50f --- /dev/null +++ b/events/syscall/linux_kernel_module_injection.go @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: Apache-2.0 +/* +Copyright (C) 2024 The Falco 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 syscall + +import ( + "os" + "os/exec" + + "github.com/falcosecurity/event-generator/events" +) + +var _ = events.Register(LinuxKernelModuleInjection) + +func LinuxKernelModuleInjection(h events.Helper) error { + if h.InContainer() { + // Shell script content + scriptContent := `#!/bin/bash + + # Run lsmod and pipe the output to awk to extract the first module name + module_name=$(lsmod | awk 'NR==2{print $1}') + + # Run modinfo on the first module and grab the module path + file_path=$(modinfo "$module_name" | awk -F ': ' '/filename/ {print $2}') + + # Run insmod with the module path + sudo insmod $file_path + ` + + scriptFileName := "temp_script.sh" + if err := os.WriteFile(scriptFileName, []byte(scriptContent), 0755); err != nil { + h.Log().WithError(err).Error("Error writing script file") + return err + } + defer os.Remove(scriptFileName) // Remove file after function return + + // Set execute permission on script file + if err := os.Chmod(scriptFileName, 0755); err != nil { + h.Log().WithError(err).Error("Error setting execute permission on script file") + return err + } + + // Execute script file with its full path + cmd := exec.Command("./" + scriptFileName) + if err := cmd.Run(); err != nil { + h.Log().WithError(err).Error("Error running script file") + return err + } + } + return nil +} From 10f97666716fd5b7f14e595ae46bb441de34ff76 Mon Sep 17 00:00:00 2001 From: GLVS Kiriti Date: Fri, 5 Apr 2024 20:44:26 +0530 Subject: [PATCH 2/2] Refactoe: Build a own kernel module and load it to kernel Signed-off-by: GLVS Kiriti --- .../syscall/linux_kernel_module_injection.go | 64 +++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/events/syscall/linux_kernel_module_injection.go b/events/syscall/linux_kernel_module_injection.go index b9e4b50f..5c352d7a 100644 --- a/events/syscall/linux_kernel_module_injection.go +++ b/events/syscall/linux_kernel_module_injection.go @@ -17,6 +17,7 @@ package syscall import ( "os" "os/exec" + "path/filepath" "github.com/falcosecurity/event-generator/events" ) @@ -25,38 +26,65 @@ var _ = events.Register(LinuxKernelModuleInjection) func LinuxKernelModuleInjection(h events.Helper) error { if h.InContainer() { - // Shell script content - scriptContent := `#!/bin/bash + // Create a unique temp directory + tempDirectoryName, err := os.MkdirTemp("/home", "falco-event-generator-") + if err != nil { + return err + } + defer os.RemoveAll(tempDirectoryName) - # Run lsmod and pipe the output to awk to extract the first module name - module_name=$(lsmod | awk 'NR==2{print $1}') + // Create a c file and make file for building a kernel module + cFilePath := filepath.Join(tempDirectoryName, "basic_driver.c") + cFileContent := `#include + #include + #include + #include + #include - # Run modinfo on the first module and grab the module path - file_path=$(modinfo "$module_name" | awk -F ': ' '/filename/ {print $2}') + // Module metadata + MODULE_AUTHOR("Falco"); + MODULE_DESCRIPTION("Hello world driver for falco"); + MODULE_LICENSE("GPL"); + + static int __init custom_init(void) { + printk(KERN_INFO "Hello from Basic kernel module."); + return 0; + } + static void __exit custom_exit(void) { + printk(KERN_INFO "Exit the kernel module"); + } - # Run insmod with the module path - sudo insmod $file_path + module_init(custom_init); + module_exit(custom_exit); ` - scriptFileName := "temp_script.sh" - if err := os.WriteFile(scriptFileName, []byte(scriptContent), 0755); err != nil { - h.Log().WithError(err).Error("Error writing script file") + if err := os.WriteFile(cFilePath, []byte(cFileContent), 0644); err != nil { return err } - defer os.Remove(scriptFileName) // Remove file after function return - // Set execute permission on script file - if err := os.Chmod(scriptFileName, 0755); err != nil { - h.Log().WithError(err).Error("Error setting execute permission on script file") + makefilePath := filepath.Join(tempDirectoryName, "Makefile") + makefileContent := `obj-m += basic_driver.o + + all: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules + clean: + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean` + + if err := os.WriteFile(makefilePath, []byte(makefileContent), 0644); err != nil { return err } - // Execute script file with its full path - cmd := exec.Command("./" + scriptFileName) + // Run make command + cmd := exec.Command("make") + cmd.Dir = tempDirectoryName if err := cmd.Run(); err != nil { - h.Log().WithError(err).Error("Error running script file") return err } + + // Load kernel module with insmod + koFilePath := filepath.Join(tempDirectoryName, "basic_driver.ko") + defer exec.Command("rmmod", "basic_driver.ko") // Unload the kernel module at end + return exec.Command("insmod", koFilePath).Run() } return nil }