From b09b51840c969a2a6abb737604def30c68dc762d Mon Sep 17 00:00:00 2001 From: Mikhail Klementev Date: Sun, 14 May 2023 16:54:12 +0000 Subject: [PATCH] feat: fetch kbuild from linux-tools for older kernels --- distro/debian/kernel.go | 115 +++++++++++++++++++++++++++++++++++++++- go.mod | 1 + go.sum | 2 + 3 files changed, 117 insertions(+), 1 deletion(-) diff --git a/distro/debian/kernel.go b/distro/debian/kernel.go index faf1d7e..ea7610a 100644 --- a/distro/debian/kernel.go +++ b/distro/debian/kernel.go @@ -2,9 +2,11 @@ package debian import ( "errors" + "sort" "strings" "time" + "github.com/Masterminds/semver" "github.com/rs/zerolog/log" "code.dumpstack.io/tools/out-of-tree/cache" @@ -37,6 +39,22 @@ type DebianKernel struct { } } +func (dk DebianKernel) HasDependency(pkgname string) bool { + for _, deppkg := range dk.Dependencies { + if strings.Contains(deppkg.Name, pkgname) { + return true + } + } + return false +} + +// use only for inline comparison +func kver(ver string) *semver.Version { + ver = strings.Replace(ver, "~", "-", -1) + ver = strings.Replace(ver, "+", "-", -1) + return semver.MustParse(ver) +} + var ( ErrNoBinaryPackages = errors.New("no binary packages found") ErrNoHeadersPackage = errors.New("no headers package found") @@ -133,6 +151,69 @@ func GetCachedKernel(deb string) (dk DebianKernel, err error) { return } +func kbuildVersion(versions []string, kpkgver string) string { + sort.Slice(versions, func(i, j int) bool { + return kver(versions[i]).GreaterThan(kver(versions[j])) + }) + + for _, v := range versions { + if v == kpkgver { + return v + } + } + + ver := kver(kpkgver) + + // Not able to find the exact version, try similar + for _, v := range versions { + cver := kver(v) + + // It's certainly not fit for purpose if the major and + // minor versions aren't the same + + if ver.Major() != cver.Major() { + continue + } + + if ver.Minor() != cver.Minor() { + continue + } + + // Use the first version that is newer than the kernel + + if ver.LessThan(cver) { + continue + } + + return v + } + + return "" +} + +func findKbuild(versions []string, kpkgver string) ( + pkg snapshot.Package, err error) { + + version := kbuildVersion(versions, kpkgver) + if version == "" { + err = errors.New("cannot find kbuild version") + return + } + + packages, err := snapshot.Packages("linux-tools", version, + `^linux-kbuild`, []string{"amd64"}, []string{"dbg"}) + if err != nil { + return + } + + if len(packages) == 0 { + err = errors.New("cannot find kbuild package") + } + + pkg = packages[0] + return +} + var ( CachePath string RefetchDays int = 7 @@ -162,9 +243,15 @@ func GetKernels() (kernels []DebianKernel, err error) { } defer c.Close() + linuxToolsVersions, err := snapshot.SourcePackageVersions("linux-tools") + if err != nil { + log.Error().Err(err).Msg("get linux-tools source pkg versions") + return + } + versions, err := snapshot.SourcePackageVersions("linux") if err != nil { - log.Error().Err(err).Msg("get source package versions") + log.Error().Err(err).Msg("get linux source package versions") return } @@ -175,6 +262,7 @@ func GetKernels() (kernels []DebianKernel, err error) { } for i, version := range versions { + // TODO move this scope to function slog := log.With().Str("version", version).Logger() slog.Debug().Msgf("%03d/%03d", i, len(versions)) @@ -207,6 +295,31 @@ func GetKernels() (kernels []DebianKernel, err error) { dk.Internal.LastFetch = time.Now() } + if !dk.HasDependency("kbuild") { + if !kver(dk.Version.Package).LessThan(kver("4.5-rc0")) { + dk.Internal.Invalid = true + dk.Internal.LastFetch = time.Now() + } else { + // Debian kernels prior to the 4.5 package + // version did not have a kbuild built from + // the linux source itself, but used the + // linux-tools source package. + kbuildpkg, err := findKbuild( + linuxToolsVersions, + dk.Version.Package, + ) + if err != nil { + dk.Internal.Invalid = true + dk.Internal.LastFetch = time.Now() + } else { + dk.Dependencies = append( + dk.Dependencies, + kbuildpkg, + ) + } + } + } + err = c.Put(dk) if err != nil { slog.Error().Err(err).Msg("put to cache") diff --git a/go.mod b/go.mod index d3026cb..e5e2372 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ replace code.dumpstack.io/tools/out-of-tree/config => ./config replace code.dumpstack.io/tools/out-of-tree/distro => ./distro require ( + github.com/Masterminds/semver v1.5.0 github.com/PuerkitoBio/goquery v1.8.1 github.com/alecthomas/kong v0.7.1 github.com/cavaliergopher/grab/v3 v3.0.1 diff --git a/go.sum b/go.sum index bf72659..ef85522 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=