93 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			93 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|    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
 | |
| }
 | 
