Files
teleport/lib/utils/kernel.go
T
Mike JensenandKrzysztof Skrzętnicki 4cba417e80 Careful handling when loading files (#31721)
* Careful handling when loading files

This commit attempts to provide a common API so that the decision of when to follow symlinks is a conscious decision.
Because Teleport (particularly the agent) runs in a privilege context, there is risk that following symlinks may allow information disclosure.

After review of the cases covered in this commit (and some additional cases where this API was not a natural fit), this does not appear to be a broad problem.  This commit however does fix the one known flaw described in the issue https://github.com/gravitational/teleport-private/issues/1009

* Apply PR feedback to rename OpenFile

* fs.go: Fix symlink evaluation

* fs.go: Fix for rebuilding absolute paths in symlink check

* fs_test.go: Add symlink testing

* Apply suggestions from code review

Co-authored-by: Krzysztof Skrzętnicki <krzysztof.skrzetnicki@goteleport.com>

* fs_test.go: Fix build for err reference

* fs.go: Apply PR feedback and consider Hardlinks

After PR discussion it was highlighted that MacOS does not guard against hardlinks in the same way linux does.  For that reason this implementation has been updated with OS conditional logic to validate against hardlinks.

* fs.go: Switch loop to range over components instead of index

* Minor improvements from PR feedback

* fs_test.go: Test public OpenFile API's and include OS specific validation

* Fix windows build

Make hardlink count lookup code build conditional to avoid undefined syscall.Stat_t.

* utils.getHardLinkCount result order update from PR feedback

* fs_windows.go: Comment improvements from PR feedback

* fs: Fix build for OSX

* Disable lint error due to unecessary cast on linux

---------

Co-authored-by: Krzysztof Skrzętnicki <krzysztof.skrzetnicki@goteleport.com>
2023-09-15 14:44:31 +00:00

104 lines
2.8 KiB
Go

/*
Copyright 2019 Gravitational, Inc.
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.
*/
package utils
import (
"fmt"
"io"
"os"
"regexp"
"runtime"
"github.com/coreos/go-semver/semver"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/api/constants"
)
// KernelVersion parses /proc/sys/kernel/osrelease and returns the kernel
// version of the host. This only returns something meaningful on Linux.
func KernelVersion() (*semver.Version, error) {
if runtime.GOOS != constants.LinuxOS {
return nil, trace.BadParameter("requested kernel version on non-Linux host")
}
file, err := OpenFileNoUnsafeLinks("/proc/sys/kernel/osrelease")
if err != nil {
return nil, trace.Wrap(err)
}
defer file.Close()
ver, err := kernelVersion(file)
if err != nil {
return nil, trace.Wrap(err)
}
return ver, nil
}
// kernelVersionRegex extracts the first three digits of a version from
// a kernel version - this strips off any additional digits or additional
// information appended to the kernel version e.g:
// 5.15.68.1-microsoft-standard-WSL2 => 5.15.68
var kernelVersionRegex = regexp.MustCompile(`^\d+\.\d+\.\d+`)
// kernelVersion reads in the kernel version from the reader and returns
// a *semver.Version.
func kernelVersion(reader io.Reader) (*semver.Version, error) {
buf, err := io.ReadAll(reader)
if err != nil {
return nil, trace.Wrap(err)
}
s := kernelVersionRegex.FindString(string(buf))
if s == "" {
return nil, trace.BadParameter(
"unable to extract kernel semver from string %q",
string(buf),
)
}
ver, err := semver.NewVersion(s)
if err != nil {
return nil, trace.Wrap(err)
}
return ver, nil
}
const btfFile = "/sys/kernel/btf/vmlinux"
// HasBTF checks that the kernel has been compiled with BTF support and
// that the type information can be opened. Returns nil if BTF is there
// and accessible, otherwise an error describing the problem.
func HasBTF() error {
if runtime.GOOS != constants.LinuxOS {
return trace.BadParameter("requested kernel version on non-Linux host")
}
file, err := OpenFileNoUnsafeLinks(btfFile)
if err == nil {
file.Close()
return nil
}
if os.IsNotExist(err) {
return fmt.Errorf("%v was not found. Make sure the kernel was compiled with BTF support (CONFIG_DEBUG_INFO_BTF)", btfFile)
}
return fmt.Errorf("failed to open %v: %v", btfFile, err)
}