github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/system/kernelversion/kernel_linux.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 16 File copied and customized based on 17 https://github.com/moby/moby/tree/v20.10.14/profiles/seccomp/kernel_linux.go 18 19 File copied from 20 https://github.com/containerd/containerd/blob/v1.7.5/contrib/seccomp/kernelversion/kernel_linux.go 21 */ 22 23 package kernelversion 24 25 import ( 26 "bytes" 27 "fmt" 28 "sync" 29 30 "golang.org/x/sys/unix" 31 ) 32 33 // KernelVersion holds information about the kernel. 34 type KernelVersion struct { 35 Kernel uint64 // Version of the Kernel (i.e., the "4" in "4.1.2-generic") 36 Major uint64 // Major revision of the Kernel (i.e., the "1" in "4.1.2-generic") 37 } 38 39 func (k *KernelVersion) String() string { 40 if k.Kernel > 0 || k.Major > 0 { 41 return fmt.Sprintf("%d.%d", k.Kernel, k.Major) 42 } 43 return "" 44 } 45 46 var ( 47 currentKernelVersion *KernelVersion 48 kernelVersionError error 49 once sync.Once 50 ) 51 52 // getKernelVersion gets the current kernel version. 53 func getKernelVersion() (*KernelVersion, error) { 54 once.Do(func() { 55 var uts unix.Utsname 56 if err := unix.Uname(&uts); err != nil { 57 return 58 } 59 // Remove the \x00 from the release for Atoi to parse correctly 60 currentKernelVersion, kernelVersionError = parseRelease(string(uts.Release[:bytes.IndexByte(uts.Release[:], 0)])) 61 }) 62 return currentKernelVersion, kernelVersionError 63 } 64 65 // parseRelease parses a string and creates a KernelVersion based on it. 66 func parseRelease(release string) (*KernelVersion, error) { 67 var version KernelVersion 68 69 // We're only make sure we get the "kernel" and "major revision". Sometimes we have 70 // 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64. 71 _, err := fmt.Sscanf(release, "%d.%d", &version.Kernel, &version.Major) 72 if err != nil { 73 return nil, fmt.Errorf("failed to parse kernel version %q: %w", release, err) 74 } 75 return &version, nil 76 } 77 78 // GreaterEqualThan checks if the host's kernel version is greater than, or 79 // equal to the given kernel version v. Only "kernel version" and "major revision" 80 // can be specified (e.g., "3.12") and will be taken into account, which means 81 // that 3.12.25-gentoo and 3.12-1-amd64 are considered equal (kernel: 3, major: 12). 82 func GreaterEqualThan(minVersion KernelVersion) (bool, error) { 83 kv, err := getKernelVersion() 84 if err != nil { 85 return false, err 86 } 87 if kv.Kernel > minVersion.Kernel { 88 return true, nil 89 } 90 if kv.Kernel == minVersion.Kernel && kv.Major >= minVersion.Major { 91 return true, nil 92 } 93 return false, nil 94 }