From 686491226941fc368866c3749f8598e869db011a Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Fri, 4 Oct 2024 09:49:42 +0200 Subject: [PATCH] Isolate the testing import in test code testing_mocks_linux.go imports the testing package, and that import leaks into any binary built with securejoin. This causes issues in projects which check for that, such as Kubernetes (see https://github.com/kubernetes/kubernetes/pull/127832 and its tests). This adds a level of indirection for hooks used to force testing behaviour in procfs_linux.go, so that the mocks can be defined only in _test.go files. This ensures that the testing package is only pulled in for tests. Signed-off-by: Stephen Kitt --- procfs_linux.go | 25 +++++++++++++++---- ...ks_linux.go => testing_mocks_linux_test.go | 8 ++++++ 2 files changed, 28 insertions(+), 5 deletions(-) rename testing_mocks_linux.go => testing_mocks_linux_test.go (84%) diff --git a/procfs_linux.go b/procfs_linux.go index fa7929a..ba179de 100644 --- a/procfs_linux.go +++ b/procfs_linux.go @@ -134,7 +134,7 @@ func clonePrivateProcMount() (_ *os.File, Err error) { // we can be sure there are no over-mounts and so if the root is valid then // we're golden. Otherwise, we have to deal with over-mounts. procfsHandle, err := openTree(nil, "/proc", unix.OPEN_TREE_CLONE) - if err != nil || testingForcePrivateProcRootOpenTreeAtRecursive(procfsHandle) { + if err != nil || hookForcePrivateProcRootOpenTreeAtRecursive(procfsHandle) { procfsHandle, err = openTree(nil, "/proc", unix.OPEN_TREE_CLONE|unix.AT_RECURSIVE) } if err != nil { @@ -152,13 +152,13 @@ func clonePrivateProcMount() (_ *os.File, Err error) { } func privateProcRoot() (*os.File, error) { - if !hasNewMountApi() || testingForceGetProcRootUnsafe() { + if !hasNewMountApi() || hookForceGetProcRootUnsafe() { return nil, fmt.Errorf("new mount api: %w", unix.ENOTSUP) } // Try to create a new procfs mount from scratch if we can. This ensures we // can get a procfs mount even if /proc is fake (for whatever reason). procRoot, err := newPrivateProcMount() - if err != nil || testingForcePrivateProcRootOpenTree(procRoot) { + if err != nil || hookForcePrivateProcRootOpenTree(procRoot) { // Try to clone /proc then... procRoot, err = clonePrivateProcMount() } @@ -227,10 +227,10 @@ func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThread // Figure out what prefix we want to use. threadSelf := "thread-self/" - if !hasProcThreadSelf() || testingForceProcSelfTask() { + if !hasProcThreadSelf() || hookForceProcSelfTask() { /// Pre-3.17 kernels don't have /proc/thread-self, so do it manually. threadSelf = "self/task/" + strconv.Itoa(unix.Gettid()) + "/" - if _, err := fstatatFile(procRoot, threadSelf, unix.AT_SYMLINK_NOFOLLOW); err != nil || testingForceProcSelf() { + if _, err := fstatatFile(procRoot, threadSelf, unix.AT_SYMLINK_NOFOLLOW); err != nil || hookForceProcSelf() { // In this case, we running in a pid namespace that doesn't match // the /proc mount we have. This can happen inside runc. // @@ -424,3 +424,18 @@ func checkProcSelfFdPath(path string, file *os.File) error { } return nil } + +// Test hooks +var hookForcePrivateProcRootOpenTree = func(_ *os.File) bool { + return false +} + +var hookForcePrivateProcRootOpenTreeAtRecursive = hookForcePrivateProcRootOpenTree + +var hookForceGetProcRootUnsafe = func() bool { + return false +} + +var hookForceProcSelfTask = hookForceGetProcRootUnsafe + +var hookForceProcSelf = hookForceGetProcRootUnsafe diff --git a/testing_mocks_linux.go b/testing_mocks_linux_test.go similarity index 84% rename from testing_mocks_linux.go rename to testing_mocks_linux_test.go index a3aedf0..c3d554c 100644 --- a/testing_mocks_linux.go +++ b/testing_mocks_linux_test.go @@ -66,3 +66,11 @@ func testingForceProcSelf() bool { return testing.Testing() && testingForceProcThreadSelf != nil && *testingForceProcThreadSelf >= forceProcSelf } + +func init() { + hookForceGetProcRootUnsafe = testingForceGetProcRootUnsafe + hookForcePrivateProcRootOpenTree = testingForcePrivateProcRootOpenTree + hookForcePrivateProcRootOpenTreeAtRecursive = testingForcePrivateProcRootOpenTreeAtRecursive + hookForceProcSelf = testingForceProcSelf + hookForceProcSelfTask = testingForceProcSelfTask +}