From e5856c193115e0cb4548fe92f0127a9657c5540b Mon Sep 17 00:00:00 2001 From: Mikhail Klementev Date: Sat, 17 Aug 2019 15:12:48 +0000 Subject: [PATCH] Implements non-regex way to set kernel version --- CHANGELOG.md | 2 + config/config.go | 92 ++++++++++++++++++++++- config/config_test.go | 37 ++++++++- examples/kernel-exploit/.out-of-tree.toml | 7 +- 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ed2866..206b3aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,8 @@ - Tagging for runs. Tags write to log and can be used for statistics. +- Added non-regex way to set kernel version in .out-of-tree.toml (see examples). + ### Changed - Now if there's no base image found — out-of-tree will try to use diff --git a/config/config.go b/config/config.go index 11302e7..2f2bb68 100644 --- a/config/config.go +++ b/config/config.go @@ -5,20 +5,32 @@ package config import ( + "errors" "fmt" "io/ioutil" "os" "regexp" + "strconv" "strings" "github.com/naoina/toml" ) +type kernel struct { + Version []int + Major []int + Minor []int + Patch []int +} + // KernelMask defines the kernel type KernelMask struct { DistroType DistroType DistroRelease string // 18.04/7.4.1708/9.1 ReleaseMask string + + // Overrides ReleaseMask + Kernel kernel } // DockerName is returns stable name for docker container @@ -225,17 +237,93 @@ func ReadKernelConfig(path string) (kernelCfg KernelConfig, err error) { return } +func rangeRegexp(start, end int) (s string) { + s += "(" + for i := start; i <= end; i++ { + s += strconv.Itoa(i) + if i != end { + s += "|" + } + } + s += ")" + return +} + +func versionRegexp(l []int) (s string, err error) { + switch len(l) { + case 1: + s += strconv.Itoa(l[0]) + case 2: + s += rangeRegexp(l[0], l[1]) + default: + err = errors.New("version must contain one value or range") + return + } + return +} + +func genReleaseMask(km kernel) (mask string, err error) { + s, err := versionRegexp(km.Version) + if err != nil { + return + } + mask += s + "." + + s, err = versionRegexp(km.Major) + if err != nil { + return + } + mask += s + "." + + s, err = versionRegexp(km.Minor) + if err != nil { + return + } + mask += s + + switch len(km.Patch) { + case 0: + // ok + case 1: + mask += "-" + strconv.Itoa(km.Patch[0]) + case 2: + mask += "-" + rangeRegexp(km.Patch[0], km.Patch[1]) + default: + err = errors.New("version must contain one value or range") + return + } + + mask += "-.*" + return +} + // ReadArtifactConfig is for read .out-of-tree.toml -func ReadArtifactConfig(path string) (artifactCfg Artifact, err error) { +func ReadArtifactConfig(path string) (ka Artifact, err error) { buf, err := readFileAll(path) if err != nil { return } - err = toml.Unmarshal(buf, &artifactCfg) + err = toml.Unmarshal(buf, &ka) if err != nil { return } + for i, _ := range ka.SupportedKernels { + km := &ka.SupportedKernels[i] + if len(km.Kernel.Version) != 0 && km.ReleaseMask != "" { + s := "Only one way to define kernel version is allowed" + err = errors.New(s) + return + } + + if km.ReleaseMask == "" { + km.ReleaseMask, err = genReleaseMask(km.Kernel) + if err != nil { + return + } + } + } + return } diff --git a/config/config_test.go b/config/config_test.go index 7bf2a59..dcf899b 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -16,7 +16,7 @@ func TestMarshalUnmarshal(t *testing.T) { Type: KernelModule, } artifactCfg.SupportedKernels = append(artifactCfg.SupportedKernels, - KernelMask{Ubuntu, "18.04", ".*"}) + KernelMask{Ubuntu, "18.04", ".*", kernel{}}) buf, err := toml.Marshal(&artifactCfg) if err != nil { t.Fatal(err) @@ -28,3 +28,38 @@ func TestMarshalUnmarshal(t *testing.T) { t.Fatal(err) } } + +func TestKernelRegex(t *testing.T) { + mask := "4.4.0-(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116)-.*" + k := kernel{ + Version: []int{4}, + Major: []int{4}, + Minor: []int{0}, + Patch: []int{1, 116}, + } + + gmask, err := genReleaseMask(k) + if err != nil { + t.Fatal(err) + } + + if mask != gmask { + t.Fatal("Got", gmask, "instead of", mask) + } + + mask = "4.4.0-.*" + k = kernel{ + Version: []int{4}, + Major: []int{4}, + Minor: []int{0}, + } + + gmask, err = genReleaseMask(k) + if err != nil { + t.Fatal(err) + } + + if mask != gmask { + t.Fatal("Got", gmask, "instead of", mask) + } +} diff --git a/examples/kernel-exploit/.out-of-tree.toml b/examples/kernel-exploit/.out-of-tree.toml index 3f65cef..4f41592 100644 --- a/examples/kernel-exploit/.out-of-tree.toml +++ b/examples/kernel-exploit/.out-of-tree.toml @@ -30,4 +30,9 @@ release_mask = "4.11.0-(1|2|3|4|5|6|7|8|9|10|11|12|13|14)-.*" [[supported_kernels]] distro_type = "Ubuntu" distro_release = "16.04" -release_mask = "4.13.0-(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21)-.*" +# equivalent for "4.13.0-(1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21)-.*" +[supported_kernels.kernel] +version = [ 4 ] +major = [ 13 ] +minor = [ 0 ] +patch = [ 1, 21 ]