@@ -37,6 +37,15 @@ const (
3737 // higher precedence than other libraries on the system, but lower than
3838 // the 00-cuda-compat that is included in some containers.
3939 ldsoconfdFilenamePattern = "00-nvcr-*.conf"
40+ // defaultTopLevelLdsoconfFilePath is the standard location of the top-level ld.so.conf file.
41+ // Most container images based on a distro will have this file, but distroless container images
42+ // may not.
43+ defaultTopLevelLdsoconfFilePath = "/etc/ld.so.conf"
44+ // defaultLdsoconfdDir is the standard location for the ld.so.conf.d drop-in directory. Most
45+ // container images based on a distro will have this directory included by the top-level
46+ // ld.so.conf file, but some may not. And some container images may not have a top-level
47+ // ld.so.conf file at all.
48+ defaultLdsoconfdDir = "/etc/ld.so.conf.d"
4049)
4150
4251type Ldconfig struct {
@@ -122,20 +131,22 @@ func (l *Ldconfig) UpdateLDCache() error {
122131
123132 // Explicitly specify using /etc/ld.so.conf since the host's ldconfig may
124133 // be configured to use a different config file by default.
125- const topLevelLdsoconfFilePath = "/etc/ld.so.conf"
126- filteredDirectories , err := l .filterDirectories (topLevelLdsoconfFilePath , l .directories ... )
134+ filteredDirectories , err := l .filterDirectories (defaultTopLevelLdsoconfFilePath , l .directories ... )
127135 if err != nil {
128136 return err
129137 }
130138
131139 args := []string {
132140 filepath .Base (ldconfigPath ),
133- "-f" , topLevelLdsoconfFilePath ,
141+ "-f" , defaultTopLevelLdsoconfFilePath ,
134142 "-C" , "/etc/ld.so.cache" ,
135143 }
136144
137- if err := createLdsoconfdFile (ldsoconfdFilenamePattern , filteredDirectories ... ); err != nil {
138- return fmt .Errorf ("failed to update ld.so.conf.d: %w" , err )
145+ if err := ensureLdsoconfFile (defaultTopLevelLdsoconfFilePath , defaultLdsoconfdDir ); err != nil {
146+ return fmt .Errorf ("failed to ensure ld.so.conf file: %w" , err )
147+ }
148+ if err := createLdsoconfdFile (defaultLdsoconfdDir , ldsoconfdFilenamePattern , filteredDirectories ... ); err != nil {
149+ return fmt .Errorf ("failed to create ld.so.conf.d drop-in file: %w" , err )
139150 }
140151
141152 // In most cases, the hook will be executing a host ldconfig that may be configured widely
@@ -144,8 +155,8 @@ func (l *Ldconfig) UpdateLDCache() error {
144155 // (e.g. /usr/lib/glibc). To avoid all these cases, append the container's expected system
145156 // search paths to the top-level ld.so.conf. This will ensure they get scanned but won't
146157 // materially change the scan order.
147- if err := appendSystemSearchPathsToLdsoconf (topLevelLdsoconfFilePath , l .getSystemSearchPaths ()... ); err != nil {
148- return fmt .Errorf ("failed to append system search paths to %s: %w" , topLevelLdsoconfFilePath , err )
158+ if err := appendSystemSearchPathsToLdsoconf (defaultTopLevelLdsoconfFilePath , l .getSystemSearchPaths ()... ); err != nil {
159+ return fmt .Errorf ("failed to append system search paths to %s: %w" , defaultTopLevelLdsoconfFilePath , err )
149160 }
150161
151162 return SafeExec (ldconfigPath , args , nil )
@@ -191,19 +202,15 @@ func (l *Ldconfig) filterDirectories(configFilePath string, directories ...strin
191202 return filtered , nil
192203}
193204
194- // createLdsoconfdFile creates a file at /etc/ld.so.conf.d/.
195- // The file is created at /etc/ld.so.conf.d/{{ .pattern }} using `CreateTemp` and
196- // contains the specified directories on each line.
197- func createLdsoconfdFile (pattern string , dirs ... string ) error {
205+ // createLdsoconfdFile creates a ld.so.conf.d drop-in file with the specified directories on each
206+ // line. The file is created at `ldsoconfdDir`/{{ .pattern }} using `CreateTemp`.
207+ func createLdsoconfdFile (ldsoconfdDir , pattern string , dirs ... string ) error {
198208 if len (dirs ) == 0 {
199209 return nil
200210 }
201-
202- ldsoconfdDir := "/etc/ld.so.conf.d"
203211 if err := os .MkdirAll (ldsoconfdDir , 0755 ); err != nil {
204212 return fmt .Errorf ("failed to create ld.so.conf.d: %w" , err )
205213 }
206-
207214 configFile , err := os .CreateTemp (ldsoconfdDir , pattern )
208215 if err != nil {
209216 return fmt .Errorf ("failed to create config file: %w" , err )
@@ -217,7 +224,7 @@ func createLdsoconfdFile(pattern string, dirs ...string) error {
217224 if added [dir ] {
218225 continue
219226 }
220- _ , err = fmt .Fprintf (configFile , "%s\n " , dir )
227+ _ , err : = fmt .Fprintf (configFile , "%s\n " , dir )
221228 if err != nil {
222229 return fmt .Errorf ("failed to update config file: %w" , err )
223230 }
@@ -250,6 +257,19 @@ func appendSystemSearchPathsToLdsoconf(configFilePath string, dirs ...string) er
250257 return nil
251258}
252259
260+ // ensureLdsoconfFile creates a "standard" top-level ld.so.conf file if none exists.
261+ //
262+ // The created file will contain a single include statement for "`ldsoconfdDir`/*.conf".
263+ func ensureLdsoconfFile (topLevelLdsoconfFilePath , ldsoconfdDir string ) error {
264+ configFile , err := os .OpenFile (topLevelLdsoconfFilePath , os .O_RDWR | os .O_CREATE | os .O_EXCL , 0644 )
265+ if err != nil && ! os .IsExist (err ) {
266+ return fmt .Errorf ("failed to create top-level ld.so.conf file: %w" , err )
267+ }
268+ defer configFile .Close ()
269+ configFile .WriteString ("include " + ldsoconfdDir + "/*.conf\n " )
270+ return nil
271+ }
272+
253273// getLdsoconfDirectories returns a map of ldsoconf directories to the conf
254274// files that refer to the directory.
255275func (l * Ldconfig ) getLdsoconfDirectories (configFilePath string ) (map [string ]struct {}, error ) {
0 commit comments