diff --git a/go.mod b/go.mod index 3007c0b3b0e..dd31a11353b 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,6 @@ require ( github.com/coreos/go-oidc v2.3.0+incompatible github.com/coreos/go-systemd/v22 v22.5.0 github.com/cpuguy83/go-md2man/v2 v2.0.4 - github.com/cyphar/filepath-securejoin v0.4.1 github.com/distribution/reference v0.6.0 github.com/docker/go-units v0.5.0 github.com/emicklei/go-restful/v3 v3.11.0 @@ -142,6 +141,7 @@ require ( github.com/containerd/typeurl/v2 v2.2.2 // indirect github.com/coredns/caddy v1.1.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect + github.com/cyphar/filepath-securejoin v0.4.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/euank/go-kmsg-parser v2.0.0+incompatible // indirect diff --git a/pkg/kubelet/kubelet_server_journal.go b/pkg/kubelet/kubelet_server_journal.go index 27c3421b883..99ec4e31685 100644 --- a/pkg/kubelet/kubelet_server_journal.go +++ b/pkg/kubelet/kubelet_server_journal.go @@ -34,8 +34,6 @@ import ( "strings" "time" - securejoin "github.com/cyphar/filepath-securejoin" - utilvalidation "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" ) @@ -229,10 +227,14 @@ func (n *nodeLogQuery) validate() field.ErrorList { case len(n.Files) == 1 && n.options != (options{}): allErrs = append(allErrs, field.Invalid(field.NewPath("query"), n.Files, "cannot specify file with options")) case len(n.Files) == 1: - if fullLogFilename, err := securejoin.SecureJoin(nodeLogDir, n.Files[0]); err != nil { - allErrs = append(allErrs, field.Invalid(field.NewPath("query"), n.Files, err.Error())) - } else if _, err := os.Stat(fullLogFilename); err != nil { + if root, err := os.OpenRoot(nodeLogDir); err != nil { allErrs = append(allErrs, field.Invalid(field.NewPath("query"), n.Files, err.Error())) + } else { + // root.Close() never returns errors + defer func() { _ = root.Close() }() + if _, err := root.Stat(n.Files[0]); err != nil { + allErrs = append(allErrs, field.Invalid(field.NewPath("query"), n.Files, err.Error())) + } } } @@ -403,6 +405,30 @@ func newReaderCtx(ctx context.Context, r io.Reader) io.Reader { } } +// heuristicsCopyFileLog returns the contents of the given logFile +func heuristicsCopyFileLog(ctx context.Context, w io.Writer, logDir, logFileName string) error { + f, err := os.OpenInRoot(logDir, logFileName) + if err != nil { + return err + } + // Ignoring errors when closing a file opened read-only doesn't cause data loss + defer func() { _ = f.Close() }() + fInfo, err := f.Stat() + if err != nil { + return err + } + // This is to account for the heuristics where logs for service foo + // could be in /var/log/foo/ + if fInfo.IsDir() { + return os.ErrNotExist + } + + if _, err := io.Copy(w, newReaderCtx(ctx, f)); err != nil { + return err + } + return nil +} + func safeServiceName(s string) error { // Max length of a service name is 256 across supported OSes if len(s) > maxServiceLength { diff --git a/pkg/kubelet/kubelet_server_journal_linux.go b/pkg/kubelet/kubelet_server_journal_linux.go index bf550e6b946..156320e770b 100644 --- a/pkg/kubelet/kubelet_server_journal_linux.go +++ b/pkg/kubelet/kubelet_server_journal_linux.go @@ -21,13 +21,8 @@ package kubelet import ( "context" "fmt" - "io" - "os" "os/exec" "strings" - - securejoin "github.com/cyphar/filepath-securejoin" - unix "golang.org/x/sys/unix" ) // getLoggingCmd returns the journalctl cmd and arguments for the given nodeLogQuery and boot. Note that @@ -81,32 +76,3 @@ func checkForNativeLogger(ctx context.Context, service string) bool { // hence we search for it in the list of services known to journalctl return strings.Contains(string(output), service+".service") } - -// heuristicsCopyFileLog returns the contents of the given logFile -func heuristicsCopyFileLog(ctx context.Context, w io.Writer, logDir, logFileName string) error { - f, err := securejoin.OpenInRoot(logDir, logFileName) - if err != nil { - return err - } - // Ignoring errors when closing a file opened read-only doesn't cause data loss - defer func() { _ = f.Close() }() - fInfo, err := f.Stat() - if err != nil { - return err - } - // This is to account for the heuristics where logs for service foo - // could be in /var/log/foo/ - if fInfo.IsDir() { - return os.ErrNotExist - } - rf, err := securejoin.Reopen(f, unix.O_RDONLY) - if err != nil { - return err - } - defer func() { _ = rf.Close() }() - - if _, err := io.Copy(w, newReaderCtx(ctx, rf)); err != nil { - return err - } - return nil -} diff --git a/pkg/kubelet/kubelet_server_journal_nonlinux.go b/pkg/kubelet/kubelet_server_journal_nonlinux.go deleted file mode 100644 index a53c197a1e7..00000000000 --- a/pkg/kubelet/kubelet_server_journal_nonlinux.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build !linux - -/* -Copyright 2024 The Kubernetes 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. -*/ - -package kubelet - -import ( - "context" - "io" - "os" - - securejoin "github.com/cyphar/filepath-securejoin" -) - -// heuristicsCopyFileLog returns the contents of the given logFile -func heuristicsCopyFileLog(ctx context.Context, w io.Writer, logDir, logFileName string) error { - logFile, err := securejoin.SecureJoin(logDir, logFileName) - if err != nil { - return err - } - fInfo, err := os.Stat(logFile) - if err != nil { - return err - } - // This is to account for the heuristics where logs for service foo - // could be in /var/log/foo/ - if fInfo.IsDir() { - return os.ErrNotExist - } - - f, err := os.Open(logFile) - if err != nil { - return err - } - // Ignoring errors when closing a file opened read-only doesn't cause data loss - defer func() { _ = f.Close() }() - - if _, err := io.Copy(w, newReaderCtx(ctx, f)); err != nil { - return err - } - return nil -}