Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CWS] add ubuntu 18.04 with kernel 4.15 to CI + fix constants #11010

Merged
merged 12 commits into from
Mar 30, 2022
2 changes: 1 addition & 1 deletion .gitlab/functional_test/security_agent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ kitchen_test_security_agent_x64:
- KITCHEN_PLATFORM: "centos"
KITCHEN_OSVERS: "centos-77,rhel-85"
- KITCHEN_PLATFORM: "ubuntu"
KITCHEN_OSVERS: "ubuntu-18-04,ubuntu-18-04-3"
KITCHEN_OSVERS: "ubuntu-18-04-0,ubuntu-18-04,ubuntu-18-04-3"
- KITCHEN_PLATFORM: "ubuntu"
KITCHEN_OSVERS: "ubuntu-20-04,ubuntu-20-04-2,ubuntu-21-10"
- KITCHEN_PLATFORM: "suse"
Expand Down
13 changes: 13 additions & 0 deletions pkg/security/ebpf/kernel/kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,19 @@ func (k *Version) IsDebianKernel() bool {
return k.OsRelease["ID"] == "debian"
}

// UbuntuKernelVersion returns a parsed ubuntu kernel version or nil if not on ubuntu or if parsing failed
func (k *Version) UbuntuKernelVersion() *kernel.UbuntuKernelVersion {
if k.OsRelease["ID"] != "ubuntu" {
return nil
}

ukv, err := kernel.NewUbuntuKernelVersion(k.UnameRelease)
if err != nil {
return nil
}
return ukv
}

// IsRH7Kernel returns whether the kernel is a rh7 kernel
func (k *Version) IsRH7Kernel() bool {
return (k.OsRelease["ID"] == "centos" || k.OsRelease["ID"] == "rhel") && k.OsRelease["VERSION_ID"] == "7"
Expand Down
64 changes: 61 additions & 3 deletions pkg/security/probe/constantfetch/fallback.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,17 @@ func (f *FallbackConstantFetcher) FinishAndGetResults() (map[string]uint64, erro
func getSizeOfStructInode(kv *kernel.Version) uint64 {
sizeOf := uint64(600)

// see https://ubuntu.com/security/CVE-2019-10638
increaseSizeAbiMinVersion := map[string]int{
"generic": 99,
"generic-lpae": 99,
"lowlatency": 99,
"gke": 1058,
"gcp": 1093,
"aws": 1066,
"azure": 1082,
}

switch {
case kv.IsRH7Kernel():
sizeOf = 584
Expand All @@ -139,6 +150,12 @@ func getSizeOfStructInode(kv *kernel.Version) uint64 {
sizeOf = 584
case kv.IsAmazonLinuxKernel() && kv.IsInRangeCloseOpen(kernel.Kernel5_10, kernel.Kernel5_11):
sizeOf = 584
case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel4_16):
if ubuntuAbiVersionCheck(kv, increaseSizeAbiMinVersion) {
sizeOf = 608
} else {
sizeOf = 600
}
case kv.Code != 0 && kv.Code < kernel.Kernel4_16:
sizeOf = 608
case kv.IsInRangeCloseOpen(kernel.Kernel5_0, kernel.Kernel5_1):
Expand Down Expand Up @@ -184,7 +201,9 @@ func getSignalTTYOffset(kv *kernel.Version) uint64 {
ttyOffset = 368
case kv.IsAmazonLinuxKernel() && kv.IsInRangeCloseOpen(kernel.Kernel5_4, kernel.Kernel5_5):
ttyOffset = 400
case kv.IsInRangeCloseOpen(kernel.Kernel4_13, kernel.Kernel4_19):
case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel4_16):
ttyOffset = 368
case kv.IsInRangeCloseOpen(kernel.Kernel4_16, kernel.Kernel4_19):
ttyOffset = 376
case kv.IsInRangeCloseOpen(kernel.Kernel4_19, kernel.Kernel5_0):
ttyOffset = 400
Expand Down Expand Up @@ -279,6 +298,8 @@ func getBpfMapNameOffset(kv *kernel.Version) uint64 {
case kv.IsSLES12Kernel():
nameOffset = 176

case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel4_18):
nameOffset = 112
case kv.IsInRangeCloseOpen(kernel.Kernel4_18, kernel.Kernel5_1):
nameOffset = 176
case kv.IsInRangeCloseOpen(kernel.Kernel5_1, kernel.Kernel5_3):
Expand Down Expand Up @@ -316,6 +337,8 @@ func getBpfProgAuxOffset(kv *kernel.Version) uint64 {
switch {
case kv.IsAmazonLinuxKernel() && kv.IsInRangeCloseOpen(kernel.Kernel4_14, kernel.Kernel4_15):
auxOffset = 24
case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel4_16):
auxOffset = 24
case kv.Code >= kernel.Kernel5_13:
auxOffset = 56
}
Expand All @@ -328,7 +351,8 @@ func getBpfProgTagOffset(kv *kernel.Version) uint64 {
switch {
case kv.IsAmazonLinuxKernel() && kv.IsInRangeCloseOpen(kernel.Kernel4_14, kernel.Kernel4_15):
progTagOffset = 16
default:
case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel4_16):
progTagOffset = 16
}

return progTagOffset
Expand Down Expand Up @@ -357,7 +381,7 @@ func getBpfProgAuxIDOffset(kv *kernel.Version) uint64 {
case kv.IsAmazonLinuxKernel() && kv.IsInRangeCloseOpen(kernel.Kernel4_14, kernel.Kernel4_15):
idOffset = 16

case kv.IsInRangeCloseOpen(kernel.Kernel4_18, kernel.Kernel5_0):
case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel5_0):
idOffset = 16
case kv.IsInRangeCloseOpen(kernel.Kernel5_0, kernel.Kernel5_4):
idOffset = 20
Expand Down Expand Up @@ -387,6 +411,8 @@ func getBpfProgAuxNameOffset(kv *kernel.Version) uint64 {
case kv.IsCOSKernel() && kv.IsInRangeCloseOpen(kernel.Kernel5_10, kernel.Kernel5_11):
nameOffset = 544

case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel4_18):
nameOffset = 128
case kv.IsInRangeCloseOpen(kernel.Kernel4_18, kernel.Kernel4_19):
nameOffset = 152
case kv.IsInRangeCloseOpen(kernel.Kernel4_19, kernel.Kernel5_0):
Expand Down Expand Up @@ -435,6 +461,10 @@ func getPIDNumbersOffset(kv *kernel.Version) uint64 {

case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel5_0):
pidNumbersOffset = 48
case kv.IsInRangeCloseOpen(kernel.Kernel5_0, kernel.Kernel5_1):
pidNumbersOffset = 56
case kv.IsInRangeCloseOpen(kernel.Kernel5_1, kernel.Kernel5_3):
pidNumbersOffset = 48
case kv.IsInRangeCloseOpen(kernel.Kernel5_0, kernel.Kernel5_3):
pidNumbersOffset = 56
case kv.IsInRangeCloseOpen(kernel.Kernel5_3, kernel.Kernel5_7):
Expand Down Expand Up @@ -522,7 +552,21 @@ func getNetDeviceIfindexOffset(kv *kernel.Version) uint64 {
}

func getNetNSOffset(kv *kernel.Version) uint64 {
// see https://ubuntu.com/security/CVE-2019-10638
hashMixAbiMinVersion := map[string]int{
"generic": 60,
"generic-lpae": 60,
"lowlatency": 60,
"oracle": 1022,
"gke": 1041,
"gcp": 1042,
"aws": 1047,
"azure": 1018,
}

switch {
case kv.IsInRangeCloseOpen(kernel.Kernel4_15, kernel.Kernel4_16) && ubuntuAbiVersionCheck(kv, hashMixAbiMinVersion):
fallthrough
// Commit 355b98553789b646ed97ad801a619ff898471b92 introduces a hashmix field for security
// purposes. This commit was cherry-picked in stable releases 4.9.168, 4.14.111, 4.19.34 and 5.0.7
// and is part of master since 5.1
Expand Down Expand Up @@ -609,3 +653,17 @@ func getFlowi6SAddrOffset(kv *kernel.Version) uint64 {
func getFlowi6ULIOffset(kv *kernel.Version) uint64 {
return getFlowi6SAddrOffset(kv) + 20
}

func ubuntuAbiVersionCheck(kv *kernel.Version, minAbiPerFlavor map[string]int) bool {
ukv := kv.UbuntuKernelVersion()
if ukv == nil {
return false
}

minAbi, present := minAbiPerFlavor[ukv.Flavor]
if !present {
return false
}

return ukv.Abi >= minAbi
}
50 changes: 50 additions & 0 deletions pkg/util/kernel/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,53 @@ func parseDebianVersion(str string) (Version, error) {
}
return ParseReleaseString(match[1])
}

// UbuntuKernelVersion represents a version from an ubuntu kernel
// Please see: https://ubuntu.com/kernel for the documentation of this scheme
type UbuntuKernelVersion struct {
Major int
Minor int
Patch int // always 0
Abi int
Flavor string
}

var ubuntuKernelVersionRegex = regexp.MustCompile(`^(\d+)\.(\d+)\.(0)-(\d+)-([[:lower:]-]+)$`)

// NewUbuntuKernelVersion parses the ubuntu release string and returns a structure with each extracted fields
func NewUbuntuKernelVersion(unameRelease string) (*UbuntuKernelVersion, error) {
match := ubuntuKernelVersionRegex.FindStringSubmatch(unameRelease)
if len(match) == 0 {
return nil, fmt.Errorf("failed to parse ubuntu kernel version")
}

major, err := strconv.ParseInt(match[1], 10, 0)
if err != nil {
return nil, err
}

minor, err := strconv.ParseInt(match[2], 10, 0)
if err != nil {
return nil, err
}

patch, err := strconv.ParseInt(match[3], 10, 0)
if err != nil {
return nil, err
}

abi, err := strconv.ParseInt(match[4], 10, 0)
if err != nil {
return nil, err
}

flavor := match[5]

return &UbuntuKernelVersion{
Major: int(major),
Minor: int(minor),
Patch: int(patch),
Abi: int(abi),
Flavor: flavor,
}, nil
}
14 changes: 14 additions & 0 deletions pkg/util/kernel/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,17 @@ func TestLinuxKernelVersionCode(t *testing.T) {
assert.Equal(t, Version(197132).String(), "3.2.12")
assert.Equal(t, Version(263168).String(), "4.4.0")
}

func TestUbuntuKernelVersion(t *testing.T) {
ubuntuVersion := "5.13.0-35-generic-lpae"
ukv, err := NewUbuntuKernelVersion(ubuntuVersion)
if err != nil {
t.Fatal(err)
}

assert.Equal(t, ukv.Major, 5)
assert.Equal(t, ukv.Minor, 13)
assert.Equal(t, ukv.Patch, 0)
assert.Equal(t, ukv.Abi, 35)
assert.Equal(t, ukv.Flavor, "generic-lpae")
}
1 change: 1 addition & 0 deletions test/kitchen/platforms.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"x86_64": {
"ubuntu-14-04": "urn,Canonical:UbuntuServer:14.04.5-LTS:14.04.201905140",
"ubuntu-16-04": "urn,Canonical:UbuntuServer:16.04.0-LTS:16.04.202106110",
"ubuntu-18-04-0": "urn,Canonical:UbuntuServer:18.04-LTS:18.04.201809110",
"ubuntu-18-04": "urn,Canonical:UbuntuServer:18.04-LTS:18.04.201906040",
"ubuntu-18-04-3": "urn,Canonical:UbuntuServer:18.04-LTS:18.04.201912180",
"ubuntu-20-04": "urn,Canonical:0001-com-ubuntu-server-focal:20_04-lts:20.04.202004230",
Expand Down