@@ -22,7 +22,6 @@ import (
22
22
"os"
23
23
"path/filepath"
24
24
"strings"
25
- "syscall"
26
25
27
26
"github.com/urfave/cli/v2"
28
27
@@ -31,6 +30,15 @@ import (
31
30
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
32
31
)
33
32
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
+
34
42
type command struct {
35
43
logger logger.Interface
36
44
}
@@ -100,27 +108,29 @@ func (m command) run(c *cli.Context, cfg *options) error {
100
108
return fmt .Errorf ("failed to load container state: %v" , err )
101
109
}
102
110
103
- containerRoot , err := s .GetContainerRoot ()
111
+ containerRootDir , err := s .GetContainerRoot ()
104
112
if err != nil {
105
113
return fmt .Errorf ("failed to determined container root: %v" , err )
106
114
}
107
115
108
116
ldconfigPath := m .resolveLDConfigPath (cfg .ldconfigPath )
109
117
args := []string {filepath .Base (ldconfigPath )}
110
- if containerRoot != "" {
111
- args = append (args , "-r" , containerRoot )
118
+ if containerRootDir != "" {
119
+ args = append (args , "-r" , containerRootDir )
112
120
}
113
121
114
- if root (containerRoot ).hasPath ("/etc/ld.so.cache" ) {
122
+ containerRoot := containerRoot (containerRootDir )
123
+
124
+ if containerRoot .hasPath ("/etc/ld.so.cache" ) {
115
125
args = append (args , "-C" , "/etc/ld.so.cache" )
116
126
} else {
117
127
m .logger .Debugf ("No ld.so.cache found, skipping update" )
118
128
args = append (args , "-N" )
119
129
}
120
130
121
131
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 ... )
124
134
if err != nil {
125
135
return fmt .Errorf ("failed to update ld.so.conf.d: %v" , err )
126
136
}
@@ -132,18 +142,7 @@ func (m command) run(c *cli.Context, cfg *options) error {
132
142
// be configured to use a different config file by default.
133
143
args = append (args , "-f" , "/etc/ld.so.conf" )
134
144
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 )
147
146
}
148
147
149
148
// resolveLDConfigPath determines the LDConfig path to use for the system.
@@ -153,44 +152,46 @@ func (m command) resolveLDConfigPath(path string) string {
153
152
return strings .TrimPrefix (config .NormalizeLDConfigPath ("@" + path ), "@" )
154
153
}
155
154
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" )
164
161
return nil
165
162
}
166
163
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 )
169
170
}
170
171
171
- configFile , err := os .CreateTemp (filepath . Join ( root , "/etc/ld.so.conf.d" ), "00-nvcr-*.conf" )
172
+ configFile , err := os .CreateTemp (ldsoconfdDir , pattern )
172
173
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 )
174
175
}
175
176
defer configFile .Close ()
176
177
177
- m .logger .Debugf ("Adding folders %v to %v" , folders , configFile .Name ())
178
+ m .logger .Debugf ("Adding directories %v to %v" , dirs , configFile .Name ())
178
179
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 ] {
182
183
continue
183
184
}
184
- _ , err = configFile .WriteString (fmt .Sprintf ("%s\n " , folder ))
185
+ _ , err = configFile .WriteString (fmt .Sprintf ("%s\n " , dir ))
185
186
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 )
187
188
}
188
- configured [ folder ] = true
189
+ added [ dir ] = true
189
190
}
190
191
191
192
// 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 )
194
195
}
195
196
196
197
return nil
0 commit comments