@@ -22,7 +22,6 @@ import (
2222 "os"
2323 "path/filepath"
2424 "strings"
25- "syscall"
2625
2726 "github.com/urfave/cli/v2"
2827
@@ -31,6 +30,15 @@ import (
3130 "github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
3231)
3332
33+ const (
34+ // ldsoconfdFilenamePattern specifies the pattern for the filename
35+ // in ld.so.conf.d that includes references to the specified directories.
36+ // The 00-nvcr prefix is chosen to ensure that these libraries have a
37+ // higher precedence than other libraries on the system, but lower than
38+ // the 00-cuda-compat that is included in some containers.
39+ ldsoconfdFilenamePattern = "00-nvcr-*.conf"
40+ )
41+
3442type command struct {
3543 logger logger.Interface
3644}
@@ -100,27 +108,29 @@ func (m command) run(c *cli.Context, cfg *options) error {
100108 return fmt .Errorf ("failed to load container state: %v" , err )
101109 }
102110
103- containerRoot , err := s .GetContainerRoot ()
111+ containerRootDir , err := s .GetContainerRoot ()
104112 if err != nil {
105113 return fmt .Errorf ("failed to determined container root: %v" , err )
106114 }
107115
108116 ldconfigPath := m .resolveLDConfigPath (cfg .ldconfigPath )
109117 args := []string {filepath .Base (ldconfigPath )}
110- if containerRoot != "" {
111- args = append (args , "-r" , containerRoot )
118+ if containerRootDir != "" {
119+ args = append (args , "-r" , containerRootDir )
112120 }
113121
114- if root (containerRoot ).hasPath ("/etc/ld.so.cache" ) {
122+ containerRoot := containerRoot (containerRootDir )
123+
124+ if containerRoot .hasPath ("/etc/ld.so.cache" ) {
115125 args = append (args , "-C" , "/etc/ld.so.cache" )
116126 } else {
117127 m .logger .Debugf ("No ld.so.cache found, skipping update" )
118128 args = append (args , "-N" )
119129 }
120130
121131 folders := cfg .folders .Value ()
122- if root ( containerRoot ) .hasPath ("/etc/ld.so.conf.d" ) {
123- err := m .createConfig (containerRoot , folders )
132+ if containerRoot .hasPath ("/etc/ld.so.conf.d" ) {
133+ err := m .createLdsoconfdFile (containerRoot , ldsoconfdFilenamePattern , folders ... )
124134 if err != nil {
125135 return fmt .Errorf ("failed to update ld.so.conf.d: %v" , err )
126136 }
@@ -132,18 +142,7 @@ func (m command) run(c *cli.Context, cfg *options) error {
132142 // be configured to use a different config file by default.
133143 args = append (args , "-f" , "/etc/ld.so.conf" )
134144
135- //nolint:gosec // TODO: Can we harden this so that there is less risk of command injection
136- return syscall .Exec (ldconfigPath , args , nil )
137- }
138-
139- type root string
140-
141- func (r root ) hasPath (path string ) bool {
142- _ , err := os .Stat (filepath .Join (string (r ), path ))
143- if err != nil && os .IsNotExist (err ) {
144- return false
145- }
146- return true
145+ return m .SafeExec (ldconfigPath , args , nil )
147146}
148147
149148// resolveLDConfigPath determines the LDConfig path to use for the system.
@@ -153,44 +152,46 @@ func (m command) resolveLDConfigPath(path string) string {
153152 return strings .TrimPrefix (config .NormalizeLDConfigPath ("@" + path ), "@" )
154153}
155154
156- // createConfig creates (or updates) /etc/ld.so.conf.d/00-nvcr-<RANDOM_STRING>.conf in the container
157- // to include the required paths.
158- // Note that the 00-nvcr prefix is chosen to ensure that these libraries have
159- // a higher precedence than other libraries on the system but are applied AFTER
160- // 00-cuda-compat.conf.
161- func (m command ) createConfig (root string , folders []string ) error {
162- if len (folders ) == 0 {
163- m .logger .Debugf ("No folders to add to /etc/ld.so.conf" )
155+ // createLdsoconfdFile creates a file at /etc/ld.so.conf.d/ in the specified root.
156+ // The file is created at /etc/ld.so.conf.d/{{ .pattern }} using `CreateTemp` and
157+ // contains the specified directories on each line.
158+ func (m command ) createLdsoconfdFile (in containerRoot , pattern string , dirs ... string ) error {
159+ if len (dirs ) == 0 {
160+ m .logger .Debugf ("No directories to add to /etc/ld.so.conf" )
164161 return nil
165162 }
166163
167- if err := os .MkdirAll (filepath .Join (root , "/etc/ld.so.conf.d" ), 0755 ); err != nil {
168- return fmt .Errorf ("failed to create ld.so.conf.d: %v" , err )
164+ ldsoconfdDir , err := in .resolve ("/etc/ld.so.conf.d" )
165+ if err != nil {
166+ return err
167+ }
168+ if err := os .MkdirAll (ldsoconfdDir , 0755 ); err != nil {
169+ return fmt .Errorf ("failed to create ld.so.conf.d: %w" , err )
169170 }
170171
171- configFile , err := os .CreateTemp (filepath . Join ( root , "/etc/ld.so.conf.d" ), "00-nvcr-*.conf" )
172+ configFile , err := os .CreateTemp (ldsoconfdDir , pattern )
172173 if err != nil {
173- return fmt .Errorf ("failed to create config file: %v " , err )
174+ return fmt .Errorf ("failed to create config file: %w " , err )
174175 }
175176 defer configFile .Close ()
176177
177- m .logger .Debugf ("Adding folders %v to %v" , folders , configFile .Name ())
178+ m .logger .Debugf ("Adding directories %v to %v" , dirs , configFile .Name ())
178179
179- configured := make (map [string ]bool )
180- for _ , folder := range folders {
181- if configured [ folder ] {
180+ added := make (map [string ]bool )
181+ for _ , dir := range dirs {
182+ if added [ dir ] {
182183 continue
183184 }
184- _ , err = configFile .WriteString (fmt .Sprintf ("%s\n " , folder ))
185+ _ , err = configFile .WriteString (fmt .Sprintf ("%s\n " , dir ))
185186 if err != nil {
186- return fmt .Errorf ("failed to update ld.so.conf.d : %v " , err )
187+ return fmt .Errorf ("failed to update config file : %w " , err )
187188 }
188- configured [ folder ] = true
189+ added [ dir ] = true
189190 }
190191
191192 // The created file needs to be world readable for the cases where the container is run as a non-root user.
192- if err := os .Chmod (configFile . Name (), 0644 ); err != nil {
193- return fmt .Errorf ("failed to chmod config file: %v " , err )
193+ if err := configFile .Chmod (0644 ); err != nil {
194+ return fmt .Errorf ("failed to chmod config file: %w " , err )
194195 }
195196
196197 return nil
0 commit comments