From 96c14b0e85de91c6f02f42045371c3e51fd0becc Mon Sep 17 00:00:00 2001 From: Srijan Keshri Date: Sat, 25 Jul 2026 13:41:57 +0530 Subject: [PATCH] Skip non-regular files in tryResolveLibrary tryResolveLibrary validated candidates with filepath.EvalSymlinks, which succeeds for any existing path, including directories. Since candidates are returned on first match and /usr/lib64 is searched before /usr/lib/x86_64-linux-gnu, a stray directory named after the library in /usr/lib64 shadows the real library in a later search path and the resolved path fails to dlopen. Skip any candidate that does not resolve to a regular file so resolution continues through the remaining search paths, falling back to returning the library name as is. Signed-off-by: Srijan Keshri --- pkg/nvlib/info/root.go | 5 +++ pkg/nvlib/info/root_test.go | 86 +++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 pkg/nvlib/info/root_test.go diff --git a/pkg/nvlib/info/root.go b/pkg/nvlib/info/root.go index d38dc73..0c4d9ad 100644 --- a/pkg/nvlib/info/root.go +++ b/pkg/nvlib/info/root.go @@ -18,6 +18,7 @@ package info import ( "fmt" + "os" "path/filepath" "github.com/NVIDIA/go-nvml/pkg/dl" @@ -68,6 +69,10 @@ func (r root) tryResolveLibrary(libraryName string) string { if err != nil { continue } + info, err := os.Stat(resolved) + if err != nil || !info.Mode().IsRegular() { + continue + } return resolved } diff --git a/pkg/nvlib/info/root_test.go b/pkg/nvlib/info/root_test.go new file mode 100644 index 0000000..2ee6bd8 --- /dev/null +++ b/pkg/nvlib/info/root_test.go @@ -0,0 +1,86 @@ +/** +# Copyright (c) NVIDIA CORPORATION. All rights reserved. +# +# 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 info + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestTryResolveLibrary(t *testing.T) { + const libraryName = "libnvidia-ml.so.1" + + testCases := []struct { + description string + // dirs and files are created relative to the test root before resolving. + dirs []string + files []string + // expected is the resolved path relative to the test root, or "" if + // the input library name is expected to be returned as is. + expected string + }{ + { + description: "library in first search path", + files: []string{"usr/lib64/" + libraryName}, + expected: "usr/lib64/" + libraryName, + }, + { + description: "directory in earlier search path does not shadow library", + dirs: []string{"usr/lib64/" + libraryName}, + files: []string{"usr/lib/x86_64-linux-gnu/" + libraryName}, + expected: "usr/lib/x86_64-linux-gnu/" + libraryName, + }, + { + description: "only directories found", + dirs: []string{"usr/lib64/" + libraryName}, + expected: "", + }, + { + description: "library not found", + expected: "", + }, + } + + for _, tc := range testCases { + t.Run(tc.description, func(t *testing.T) { + testRoot := t.TempDir() + for _, d := range tc.dirs { + require.NoError(t, os.MkdirAll(filepath.Join(testRoot, d), 0o755)) + } + for _, f := range tc.files { + path := filepath.Join(testRoot, f) + require.NoError(t, os.MkdirAll(filepath.Dir(path), 0o755)) + require.NoError(t, os.WriteFile(path, []byte{}, 0o644)) + } + + resolved := root(testRoot).tryResolveLibrary(libraryName) + if tc.expected == "" { + require.Equal(t, libraryName, resolved) + return + } + + // t.TempDir may itself contain symlinks, so compare against the + // resolved expected path. + expected, err := filepath.EvalSymlinks(filepath.Join(testRoot, tc.expected)) + require.NoError(t, err) + require.Equal(t, expected, resolved) + }) + } +}