| /* |
| Copyright The containerd Authors. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /* |
| File copied and customized based on |
| https://github.com/moby/moby/tree/v20.10.14/profiles/seccomp/kernel_linux.go |
| */ |
| |
| package kernelversion |
| |
| import ( |
| "bytes" |
| "fmt" |
| "sync" |
| |
| "golang.org/x/sys/unix" |
| ) |
| |
| // KernelVersion holds information about the kernel. |
| type KernelVersion struct { |
| Kernel uint64 // Version of the Kernel (i.e., the "4" in "4.1.2-generic") |
| Major uint64 // Major revision of the Kernel (i.e., the "1" in "4.1.2-generic") |
| } |
| |
| // String implements fmt.Stringer for KernelVersion |
| func (k *KernelVersion) String() string { |
| if k.Kernel > 0 || k.Major > 0 { |
| return fmt.Sprintf("%d.%d", k.Kernel, k.Major) |
| } |
| return "" |
| } |
| |
| var ( |
| currentKernelVersion *KernelVersion |
| kernelVersionError error |
| once sync.Once |
| ) |
| |
| // getKernelVersion gets the current kernel version. |
| func getKernelVersion() (*KernelVersion, error) { |
| once.Do(func() { |
| var uts unix.Utsname |
| if err := unix.Uname(&uts); err != nil { |
| return |
| } |
| // Remove the \x00 from the release for Atoi to parse correctly |
| currentKernelVersion, kernelVersionError = parseRelease(string(uts.Release[:bytes.IndexByte(uts.Release[:], 0)])) |
| }) |
| return currentKernelVersion, kernelVersionError |
| } |
| |
| // parseRelease parses a string and creates a KernelVersion based on it. |
| func parseRelease(release string) (*KernelVersion, error) { |
| var version = KernelVersion{} |
| |
| // We're only make sure we get the "kernel" and "major revision". Sometimes we have |
| // 3.12.25-gentoo, but sometimes we just have 3.12-1-amd64. |
| _, err := fmt.Sscanf(release, "%d.%d", &version.Kernel, &version.Major) |
| if err != nil { |
| return nil, fmt.Errorf("failed to parse kernel version %q: %w", release, err) |
| } |
| return &version, nil |
| } |
| |
| // GreaterEqualThan checks if the host's kernel version is greater than, or |
| // equal to the given kernel version v. Only "kernel version" and "major revision" |
| // can be specified (e.g., "3.12") and will be taken into account, which means |
| // that 3.12.25-gentoo and 3.12-1-amd64 are considered equal (kernel: 3, major: 12). |
| func GreaterEqualThan(minVersion KernelVersion) (bool, error) { |
| kv, err := getKernelVersion() |
| if err != nil { |
| return false, err |
| } |
| if kv.Kernel > minVersion.Kernel { |
| return true, nil |
| } |
| if kv.Kernel == minVersion.Kernel && kv.Major >= minVersion.Major { |
| return true, nil |
| } |
| return false, nil |
| } |