diff --git a/policy/cilium/0039-modules_linux-Add-support-for-builtin-modules.patch b/policy/cilium/0039-modules_linux-Add-support-for-builtin-modules.patch new file mode 100644 index 00000000..bca57a67 --- /dev/null +++ b/policy/cilium/0039-modules_linux-Add-support-for-builtin-modules.patch @@ -0,0 +1,396 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: TheAifam5 +Date: Wed, 22 Feb 2023 23:36:50 +0100 +Subject: modules_linux: Add support for builtin modules + +[ upstream commit 51630941ac2f19db83d3d7a88e2a8a17fcf8e814 ] + +Previously, kernel modules names were read from the `/proc/modules` only which prevented k8s linux distribution with kernel modules builtin into the kernel to pass the validation of required kernel modules by Cilium. + +This patch adds support for systems with builtin modules by trying to read the kernel module names from following files additionally: +- `/lib/modules//modules.builtin` +- `/usr/lib/modules//modules.builtin` +- `/usr/lib/debug/lib/modules//modules.builtin` + +Fixes: #23863 + +Signed-off-by: Mateusz Paluszkiewicz (TheAifam5) +Signed-off-by: Tam Mach +--- + pkg/modules/modules_linux.go | 117 ++++++++++++++++++++++++--- + pkg/modules/modules_linux_test.go | 129 ++++++++++++++++++++++++++++++ + pkg/modules/modules_test.go | 61 -------------- + 3 files changed, 236 insertions(+), 71 deletions(-) + create mode 100644 pkg/modules/modules_linux_test.go + +diff --git a/pkg/modules/modules_linux.go b/pkg/modules/modules_linux.go +index 21dee7eba5..7fdec7105b 100644 +--- a/pkg/modules/modules_linux.go ++++ b/pkg/modules/modules_linux.go +@@ -5,22 +5,40 @@ package modules + + import ( + "bufio" ++ "errors" + "fmt" + "io" + "os" ++ "path/filepath" + "strings" ++ ++ linux "golang.org/x/sys/unix" + ) + + const ( +- modulesFilepath = "/proc/modules" ++ loadedModulesFilepath = "/proc/modules" + ) + + func moduleLoader() string { + return "modprobe" + } + +-// parseModulesFile returns the list of loaded kernel modules names. +-func parseModulesFile(r io.Reader) ([]string, error) { ++// kernelRelease returns the release string of the running kernel. ++// Its format depends on the Linux distribution and corresponds to directory ++// names in /lib/modules by convention. Some examples are 5.15.17-1-lts and ++// 4.19.0-16-amd64. ++// Note: copied from /vendor/github.com/cilium/ebpf/internal/version.go ++func kernelRelease() (string, error) { ++ var uname linux.Utsname ++ if err := linux.Uname(&uname); err != nil { ++ return "", fmt.Errorf("uname failed: %w", err) ++ } ++ ++ return linux.ByteSliceToString(uname.Release[:]), nil ++} ++ ++// parseLoadedModulesFile returns the list of loaded kernel modules names. ++func parseLoadedModulesFile(r io.Reader) ([]string, error) { + var result []string + + scanner := bufio.NewScanner(r) +@@ -45,15 +63,94 @@ func parseModulesFile(r io.Reader) ([]string, error) { + return result, nil + } + +-// listModules returns the list of loaded kernel modules names parsed from +-// /proc/modules. +-func listModules() ([]string, error) { +- fModules, err := os.Open(modulesFilepath) ++// parseBuiltinModulesFile returns the list of builtin kernel modules names. ++func parseBuiltinModulesFile(r io.Reader) ([]string, error) { ++ var result []string ++ ++ scanner := bufio.NewScanner(r) ++ scanner.Split(bufio.ScanLines) ++ ++ for scanner.Scan() { ++ modulePathRaw := scanner.Text() ++ moduleFileName := filepath.Base(modulePathRaw) ++ moduleFileExt := filepath.Ext(modulePathRaw) ++ moduleName := strings.TrimSuffix(moduleFileName, moduleFileExt) ++ result = append(result, moduleName) ++ } ++ ++ if err := scanner.Err(); err != nil { ++ return nil, err ++ } ++ ++ return result, nil ++} ++ ++// listLoadedModules returns the parsed list of loaded kernel modules names. ++func listLoadedModules() ([]string, error) { ++ fModules, err := os.Open(loadedModulesFilepath) + if err != nil { + return nil, fmt.Errorf( +- "failed to open modules information at %s: %s", +- modulesFilepath, err) ++ "failed to open loaded modules information at %s: %w", ++ loadedModulesFilepath, err) + } + defer fModules.Close() +- return parseModulesFile(fModules) ++ return parseLoadedModulesFile(fModules) ++} ++ ++// listBuiltinModules returns the parsed list of builtin kernel modules names. ++func listBuiltinModules() ([]string, error) { ++ var result []string ++ ++ locations := []string{ ++ "/lib/modules/%s/modules.builtin", ++ "/usr/lib/modules/%s/modules.builtin", ++ "/usr/lib/debug/lib/modules/%s/modules.builtin", ++ } ++ ++ release, err := kernelRelease() ++ if err != nil { ++ return nil, err ++ } ++ ++ for _, location := range locations { ++ fModulePath := fmt.Sprintf(location, release) ++ ++ fModules, err := os.Open(fModulePath) ++ if errors.Is(err, os.ErrNotExist) { ++ continue ++ } ++ ++ if err != nil { ++ return nil, fmt.Errorf( ++ "failed to open builtin modules information at %s: %w", ++ fModulePath, err) ++ } ++ ++ defer fModules.Close() ++ ++ result, err = parseBuiltinModulesFile(fModules) ++ if err != nil { ++ return nil, err ++ } ++ ++ break ++ } ++ ++ return result, nil ++} ++ ++// listModules returns the list of loaded kernel modules names parsed from ++// /proc/modules and from /lib/modules//modules.builtin. ++func listModules() ([]string, error) { ++ loadedModules, err := listLoadedModules() ++ if err != nil { ++ return nil, fmt.Errorf("failed to retrieve loaded modules names: %w", err) ++ } ++ ++ builtinModules, err := listBuiltinModules() ++ if err != nil { ++ return nil, fmt.Errorf("failed to retrieve builtin modules names: %w", err) ++ } ++ ++ return append(loadedModules, builtinModules...), nil + } +diff --git a/pkg/modules/modules_linux_test.go b/pkg/modules/modules_linux_test.go +new file mode 100644 +index 0000000000..caff016be0 +--- /dev/null ++++ b/pkg/modules/modules_linux_test.go +@@ -0,0 +1,129 @@ ++// SPDX-License-Identifier: Apache-2.0 ++// Copyright Authors of Cilium ++ ++package modules ++ ++import ( ++ "bytes" ++ ++ . "gopkg.in/check.v1" ++ ++ "github.com/cilium/cilium/pkg/checker" ++) ++ ++const ( ++ loadedModulesContent = `ebtable_nat 16384 1 - Live 0x0000000000000000 ++ebtable_broute 16384 1 - Live 0x0000000000000000 ++bridge 172032 1 ebtable_broute, Live 0x0000000000000000 ++ip6table_nat 16384 1 - Live 0x0000000000000000 ++nf_nat_ipv6 16384 1 ip6table_nat, Live 0x0000000000000000 ++ip6table_mangle 16384 1 - Live 0x0000000000000000 ++ip6table_raw 16384 1 - Live 0x0000000000000000 ++ip6table_security 16384 1 - Live 0x0000000000000000 ++iptable_nat 16384 1 - Live 0x0000000000000000 ++nf_nat_ipv4 16384 1 iptable_nat, Live 0x0000000000000000 ++iptable_mangle 16384 1 - Live 0x0000000000000000 ++iptable_raw 16384 1 - Live 0x0000000000000000 ++iptable_security 16384 1 - Live 0x0000000000000000 ++ebtable_filter 16384 1 - Live 0x0000000000000000 ++ebtables 36864 3 ebtable_nat,ebtable_broute,ebtable_filter, Live 0x0000000000000000 ++ip6table_filter 16384 1 - Live 0x0000000000000000 ++ip6_tables 28672 5 ip6table_nat,ip6table_mangle,ip6table_raw,ip6table_security,ip6table_filter, Live 0x0000000000000000 ++iptable_filter 16384 1 - Live 0x0000000000000000 ++ip_tables 28672 5 iptable_nat,iptable_mangle,iptable_raw,iptable_security,iptable_filter, Live 0x0000000000000000 ++x_tables 40960 23 xt_multiport,xt_nat,xt_addrtype,xt_mark,xt_comment,xt_CHECKSUM,ipt_MASQUERADE,xt_tcpudp,ip6t_rpfilter,ip6t_REJECT,ipt_REJECT,xt_conntrack,ip6table_mangle,ip6table_raw,ip6table_security,iptable_mangle,iptable_raw,iptable_security,ebtables,ip6table_filter,ip6_tables,iptable_filter,ip_tables, Live 0x0000000000000000` ++ ++ builtinModulesContent = `kernel/net/bridge/netfilter/ebtable_nat.ko ++kernel/net/bridge/netfilter/ebtable_broute.ko ++kernel/net/bridge/bridge.ko ++kernel/net/ipv6/netfilter/ip6table_nat.ko ++kernel/net/ipv6/netfilter/nf_nat_ipv6.ko ++kernel/net/ipv6/netfilter/ip6table_mangle.ko ++kernel/net/ipv6/netfilter/ip6table_raw.ko ++kernel/net/ipv6/netfilter/ip6table_security.ko ++kernel/net/ipv4/netfilter/iptable_nat.ko ++kernel/net/ipv4/netfilter/nf_nat_ipv4.ko ++kernel/net/ipv4/netfilter/iptable_mangle.ko ++kernel/net/ipv4/netfilter/iptable_raw.ko ++kernel/net/ipv4/netfilter/iptable_security.ko ++kernel/net/bridge/netfilter/ebtable_filter.ko ++kernel/net/bridge/netfilter/ebtables.ko ++kernel/net/ipv6/netfilter/ip6table_filter.ko ++kernel/net/ipv6/netfilter/ip6_tables.ko ++kernel/net/ipv4/netfilter/iptable_filter.ko ++kernel/net/ipv4/netfilter/ip_tables.ko ++kernel/net/netfilter/x_tables.ko` ++) ++ ++type ModulesLinuxTestSuite struct{} ++ ++var _ = Suite(&ModulesLinuxTestSuite{}) ++ ++func (s *ModulesLinuxTestSuite) TestParseLoadedModuleFile(c *C) { ++ expectedLength := 20 ++ expectedModules := []string{ ++ "ebtable_nat", ++ "ebtable_broute", ++ "bridge", ++ "ip6table_nat", ++ "nf_nat_ipv6", ++ "ip6table_mangle", ++ "ip6table_raw", ++ "ip6table_security", ++ "iptable_nat", ++ "nf_nat_ipv4", ++ "iptable_mangle", ++ "iptable_raw", ++ "iptable_security", ++ "ebtable_filter", ++ "ebtables", ++ "ip6table_filter", ++ "ip6_tables", ++ "iptable_filter", ++ "ip_tables", ++ "x_tables", ++ } ++ ++ r := bytes.NewBuffer([]byte(loadedModulesContent)) ++ moduleInfos, err := parseLoadedModulesFile(r) ++ c.Assert(err, IsNil) ++ c.Assert(moduleInfos, HasLen, expectedLength) ++ c.Assert(moduleInfos, checker.DeepEquals, expectedModules) ++} ++ ++func (s *ModulesLinuxTestSuite) TestParseBuiltinModuleFile(c *C) { ++ expectedLength := 20 ++ expectedModules := []string{ ++ "ebtable_nat", ++ "ebtable_broute", ++ "bridge", ++ "ip6table_nat", ++ "nf_nat_ipv6", ++ "ip6table_mangle", ++ "ip6table_raw", ++ "ip6table_security", ++ "iptable_nat", ++ "nf_nat_ipv4", ++ "iptable_mangle", ++ "iptable_raw", ++ "iptable_security", ++ "ebtable_filter", ++ "ebtables", ++ "ip6table_filter", ++ "ip6_tables", ++ "iptable_filter", ++ "ip_tables", ++ "x_tables", ++ } ++ ++ r := bytes.NewBuffer([]byte(builtinModulesContent)) ++ moduleInfos, err := parseBuiltinModulesFile(r) ++ c.Assert(err, IsNil) ++ c.Assert(moduleInfos, HasLen, expectedLength) ++ c.Assert(moduleInfos, checker.DeepEquals, expectedModules) ++} ++ ++func (s *ModulesLinuxTestSuite) TestListModules(c *C) { ++ _, err := listModules() ++ c.Assert(err, IsNil) ++} +diff --git a/pkg/modules/modules_test.go b/pkg/modules/modules_test.go +index 382eb8d780..6bff3ef799 100644 +--- a/pkg/modules/modules_test.go ++++ b/pkg/modules/modules_test.go +@@ -6,7 +6,6 @@ + package modules + + import ( +- "bytes" + "testing" + + . "gopkg.in/check.v1" +@@ -14,29 +13,6 @@ import ( + "github.com/cilium/cilium/pkg/checker" + ) + +-const ( +- modulesContent = `ebtable_nat 16384 1 - Live 0x0000000000000000 +-ebtable_broute 16384 1 - Live 0x0000000000000000 +-bridge 172032 1 ebtable_broute, Live 0x0000000000000000 +-ip6table_nat 16384 1 - Live 0x0000000000000000 +-nf_nat_ipv6 16384 1 ip6table_nat, Live 0x0000000000000000 +-ip6table_mangle 16384 1 - Live 0x0000000000000000 +-ip6table_raw 16384 1 - Live 0x0000000000000000 +-ip6table_security 16384 1 - Live 0x0000000000000000 +-iptable_nat 16384 1 - Live 0x0000000000000000 +-nf_nat_ipv4 16384 1 iptable_nat, Live 0x0000000000000000 +-iptable_mangle 16384 1 - Live 0x0000000000000000 +-iptable_raw 16384 1 - Live 0x0000000000000000 +-iptable_security 16384 1 - Live 0x0000000000000000 +-ebtable_filter 16384 1 - Live 0x0000000000000000 +-ebtables 36864 3 ebtable_nat,ebtable_broute,ebtable_filter, Live 0x0000000000000000 +-ip6table_filter 16384 1 - Live 0x0000000000000000 +-ip6_tables 28672 5 ip6table_nat,ip6table_mangle,ip6table_raw,ip6table_security,ip6table_filter, Live 0x0000000000000000 +-iptable_filter 16384 1 - Live 0x0000000000000000 +-ip_tables 28672 5 iptable_nat,iptable_mangle,iptable_raw,iptable_security,iptable_filter, Live 0x0000000000000000 +-x_tables 40960 23 xt_multiport,xt_nat,xt_addrtype,xt_mark,xt_comment,xt_CHECKSUM,ipt_MASQUERADE,xt_tcpudp,ip6t_rpfilter,ip6t_REJECT,ipt_REJECT,xt_conntrack,ip6table_mangle,ip6table_raw,ip6table_security,iptable_mangle,iptable_raw,iptable_security,ebtables,ip6table_filter,ip6_tables,iptable_filter,ip_tables, Live 0x0000000000000000` +-) +- + // Hook up gocheck into the "go test" runner. + func Test(t *testing.T) { + TestingT(t) +@@ -116,40 +92,3 @@ func (s *ModulesTestSuite) TestFindModules(c *C) { + c.Assert(diff, checker.DeepEquals, tc.expectedDiff) + } + } +- +-func (s *ModulesTestSuite) TestParseModuleFile(c *C) { +- expectedLength := 20 +- expectedModules := []string{ +- "ebtable_nat", +- "ebtable_broute", +- "bridge", +- "ip6table_nat", +- "nf_nat_ipv6", +- "ip6table_mangle", +- "ip6table_raw", +- "ip6table_security", +- "iptable_nat", +- "nf_nat_ipv4", +- "iptable_mangle", +- "iptable_raw", +- "iptable_security", +- "ebtable_filter", +- "ebtables", +- "ip6table_filter", +- "ip6_tables", +- "iptable_filter", +- "ip_tables", +- "x_tables", +- } +- +- r := bytes.NewBuffer([]byte(modulesContent)) +- moduleInfos, err := parseModulesFile(r) +- c.Assert(err, IsNil) +- c.Assert(moduleInfos, HasLen, expectedLength) +- c.Assert(moduleInfos, checker.DeepEquals, expectedModules) +-} +- +-func (s *ModulesTestSuite) TestListModules(c *C) { +- _, err := listModules() +- c.Assert(err, IsNil) +-} +-- +2.39.5 (Apple Git-154) +