| package seccomp |
| |
| import ( |
| "bytes" |
| "fmt" |
| "sync" |
| |
| "golang.org/x/sys/unix" |
| ) |
| |
| 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 |
| } |
| |
| // kernelGreaterEqualThan 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 kernelGreaterEqualThan(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 |
| } |