From 2cde15029abd6751ce742fadd1bc5c51c7886633 Mon Sep 17 00:00:00 2001 From: Haleygo Date: Mon, 26 Apr 2021 16:54:02 +0800 Subject: [PATCH] fix return code when request /logs with long file name --- pkg/routes/logs.go | 20 +++++++++++++++++ pkg/routes/logs_test.go | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 pkg/routes/logs_test.go diff --git a/pkg/routes/logs.go b/pkg/routes/logs.go index 1922a381ede..17fbdcc1be6 100644 --- a/pkg/routes/logs.go +++ b/pkg/routes/logs.go @@ -18,7 +18,9 @@ package routes import ( "net/http" + "os" "path" + "syscall" "github.com/emicklei/go-restful" ) @@ -42,6 +44,12 @@ func (l Logs) Install(c *restful.Container) { func logFileHandler(req *restful.Request, resp *restful.Response) { logdir := "/var/log" actual := path.Join(logdir, req.PathParameter("logpath")) + + // check filename length first, return 404 if it's oversize. + if logFileNameIsTooLong(actual) { + http.Error(resp, "file not found", http.StatusNotFound) + return + } http.ServeFile(resp.ResponseWriter, req.Request, actual) } @@ -49,3 +57,15 @@ func logFileListHandler(req *restful.Request, resp *restful.Response) { logdir := "/var/log" http.ServeFile(resp.ResponseWriter, req.Request, logdir) } + +// logFileNameIsTooLong checks filename length, returns true if it's longer than 255. +// cause http.ServeFile returns default error code 500 except for NotExist and Forbidden, but we need to separate the real 500 from oversize filename here. +func logFileNameIsTooLong(filePath string) bool { + _, err := os.Stat(filePath) + if err != nil { + if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENAMETOOLONG { + return true + } + } + return false +} diff --git a/pkg/routes/logs_test.go b/pkg/routes/logs_test.go new file mode 100644 index 00000000000..0b2ede3023a --- /dev/null +++ b/pkg/routes/logs_test.go @@ -0,0 +1,48 @@ +/* +Copyright 2021 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 routes + +import ( + "fmt" + "os" + "testing" +) + +func TestPreCheckLogFileNameLength(t *testing.T) { + oversizeFileName := fmt.Sprintf("%0256s", "a") + normalFileName := fmt.Sprintf("%0255s", "a") + + // check file with oversize name. + if !logFileNameIsTooLong(oversizeFileName) { + t.Error("failed to check oversize filename") + } + + // check file with normal name which doesn't exist. + if logFileNameIsTooLong(normalFileName) { + t.Error("failed to check normal filename") + } + + // check file with normal name which does exist. + _, err := os.Create(normalFileName) + if err != nil { + t.Error("failed to create test file") + } + defer os.Remove(normalFileName) + if logFileNameIsTooLong(normalFileName) { + t.Error("failed to check normal filename") + } +}