Skip to content

Commit 5790adc

Browse files
elezarjfroy
authored andcommitted
Fix update of ldcache on non-debian containers
This change ensures that the ldcache in a non-debian container includes libraries at /lib64 and /usr/lib64 when running on debian host. This is required because the system search paths do not include these folders by default resulting in a non-debian container missing system libraries from the ldcache. Signed-off-by: Evan Lezar <[email protected]> Signed-off-by: Jean-Francois Roy <[email protected]>
1 parent bad48b6 commit 5790adc

File tree

3 files changed

+46
-8
lines changed

3 files changed

+46
-8
lines changed

internal/ldconfig/ldconfig.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ func NewRunner(id string, ldconfigPath string, containerRoot string, additionala
7676
// This struct is used to perform operations on the ldcache and libraries in a
7777
// particular root (e.g. a container).
7878
//
79-
// args[0] is the reexec initializer function name
79+
// args[0] is the reexec initializer function name and is required.
80+
//
8081
// The following flags are required:
8182
//
8283
// --ldconfig-path=LDCONFIG_PATH the path to ldconfig on the host
@@ -85,16 +86,20 @@ func NewRunner(id string, ldconfigPath string, containerRoot string, additionala
8586
// The following flags are optional:
8687
//
8788
// --is-debian-like-host Indicates that the host system is debian-based.
89+
// See https://github.com/NVIDIA/nvidia-container-toolkit/pull/1444
8890
//
8991
// The remaining args are folders where soname symlinks need to be created.
9092
func NewFromArgs(args ...string) (*Ldconfig, error) {
9193
if len(args) < 1 {
9294
return nil, fmt.Errorf("incorrect arguments: %v", args)
9395
}
94-
fs := flag.NewFlagSet(args[1], flag.ExitOnError)
96+
fs := flag.NewFlagSet("ldconfig-options", flag.ExitOnError)
9597
ldconfigPath := fs.String("ldconfig-path", "", "the path to ldconfig on the host")
9698
containerRoot := fs.String("container-root", "", "the path in which ldconfig must be run")
97-
isDebianLikeHost := fs.Bool("is-debian-like-host", false, "the hook is running from a Debian-like host")
99+
isDebianLikeHost := fs.Bool("is-debian-like-host", false, `indicates that the host system is debian-based.
100+
This allows us to handle the case where there are differences in behavior
101+
between the ldconfig from the host (as executed from an update-ldcache hook) and
102+
ldconfig in the container. Such differences include system search paths.`)
98103
if err := fs.Parse(args[1:]); err != nil {
99104
return nil, err
100105
}
@@ -126,7 +131,7 @@ func (l *Ldconfig) UpdateLDCache() error {
126131

127132
// Explicitly specify using /etc/ld.so.conf since the host's ldconfig may
128133
// be configured to use a different config file by default.
129-
filteredDirectories, err := l.filterDirectories(defaultTopLevelLdsoconfFilePath, l.directories...)
134+
filteredDirectories, ldconfigDirs, err := l.filterDirectories(defaultTopLevelLdsoconfFilePath, l.directories...)
130135
if err != nil {
131136
return err
132137
}
@@ -136,6 +141,19 @@ func (l *Ldconfig) UpdateLDCache() error {
136141
"-f", defaultTopLevelLdsoconfFilePath,
137142
"-C", "/etc/ld.so.cache",
138143
}
144+
// If we are running in a non-debian container on a debian host we also
145+
// need to add the system directories for non-debian hosts to the list of
146+
// folders processed by ldconfig.
147+
// We only do this if they are not already tracked, since the folders on
148+
// on the command line have a higher priority than folders in ld.so.conf.
149+
if l.isDebianLikeHost && !l.isDebianLikeContainer {
150+
for _, systemSearchPath := range l.getSystemSearchPaths() {
151+
if _, ok := ldconfigDirs[systemSearchPath]; ok {
152+
continue
153+
}
154+
args = append(args, "/lib64", "/usr/lib64")
155+
}
156+
}
139157

140158
if err := ensureLdsoconfFile(defaultTopLevelLdsoconfFilePath, defaultLdsoconfdDir); err != nil {
141159
return fmt.Errorf("failed to ensure ld.so.conf file: %w", err)
@@ -176,10 +194,10 @@ func (l *Ldconfig) prepareRoot() (string, error) {
176194
return ldconfigPath, nil
177195
}
178196

179-
func (l *Ldconfig) filterDirectories(configFilePath string, directories ...string) ([]string, error) {
197+
func (l *Ldconfig) filterDirectories(configFilePath string, directories ...string) ([]string, map[string]struct{}, error) {
180198
ldconfigDirs, err := l.getLdsoconfDirectories(configFilePath)
181199
if err != nil {
182-
return nil, err
200+
return nil, nil, err
183201
}
184202

185203
var filtered []string
@@ -188,8 +206,9 @@ func (l *Ldconfig) filterDirectories(configFilePath string, directories ...strin
188206
continue
189207
}
190208
filtered = append(filtered, d)
209+
ldconfigDirs[d] = struct{}{}
191210
}
192-
return filtered, nil
211+
return filtered, ldconfigDirs, nil
193212
}
194213

195214
// createLdsoconfdFile creates a ld.so.conf.d drop-in file with the specified directories on each

internal/ldconfig/ldconfig_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ include INCLUDED_PATTERN*
118118
l := &Ldconfig{
119119
isDebianLikeContainer: true,
120120
}
121-
filtered, err := l.filterDirectories(topLevelConfPath, tc.input...)
121+
filtered, _, err := l.filterDirectories(topLevelConfPath, tc.input...)
122122

123123
require.NoError(t, err)
124124
require.Equal(t, tc.expected, filtered)

tests/e2e/nvidia-container-toolkit_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,4 +570,23 @@ EOF`)
570570
Expect(output).To(Equal(expectedOutput))
571571
})
572572
})
573+
574+
When("running a ubi9 container", Ordered, func() {
575+
var (
576+
expectedOutput string
577+
)
578+
BeforeAll(func(ctx context.Context) {
579+
_, _, err := runner.Run(`docker pull redhat/ubi9`)
580+
Expect(err).ToNot(HaveOccurred())
581+
582+
expectedOutput, _, err = runner.Run(`docker run --rm --runtime=runc redhat/ubi9 bash -c "ldconfig -p | grep libc.so."`)
583+
Expect(err).ToNot(HaveOccurred())
584+
})
585+
586+
It("should include the system libraries when using the nvidia-container-runtime", func(ctx context.Context) {
587+
output, _, err := runner.Run(`docker run --rm --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all redhat/ubi9 bash -c "ldconfig -p | grep libc.so."`)
588+
Expect(err).ToNot(HaveOccurred())
589+
Expect(output).To(Equal(expectedOutput))
590+
})
591+
})
573592
})

0 commit comments

Comments
 (0)