Skip to content

Commit a9727db

Browse files
Disable chmod-hook by default
This pull request introduces enhanced configurability for nvidia-ctk cdi generate, allowing users to explicitly enable or disable specific hooks, with enabled hooks taking precedence over disabled ones. If "enable-hook" is set to "all" an error will be displayed as this is not supported. The Hook CHMOD is now disabled by default, and can be enabled via the new cdi generate flag "enable-hook". This patch also implement unit tests for NewHookCreator and methods. Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]> Signed-off-by: Evan Lezar <[email protected]>
1 parent 4507575 commit a9727db

File tree

9 files changed

+661
-31
lines changed

9 files changed

+661
-31
lines changed

cmd/nvidia-ctk-installer/toolkit/toolkit_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ devices:
8484
hostPath: /host/driver/root/dev/nvidia-caps-imex-channels/channel1
8585
- path: /dev/nvidia-caps-imex-channels/channel2047
8686
hostPath: /host/driver/root/dev/nvidia-caps-imex-channels/channel2047
87+
- path: /dev/nvidia-caps/nvidia-cap1
88+
hostPath: /host/driver/root/dev/nvidia-caps/nvidia-cap1
8789
containerEdits:
8890
env:
8991
- NVIDIA_CTK_LIBCUDA_DIR=/lib/x86_64-linux-gnu

cmd/nvidia-ctk/cdi/generate/generate.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type options struct {
6262
configSearchPaths []string
6363
librarySearchPaths []string
6464
disabledHooks []string
65+
enabledHooks []string
6566

6667
csv struct {
6768
files []string
@@ -214,6 +215,13 @@ func (m command) build() *cli.Command {
214215
Destination: &opts.disabledHooks,
215216
Sources: cli.EnvVars("NVIDIA_CTK_CDI_GENERATE_DISABLED_HOOKS"),
216217
},
218+
&cli.StringSliceFlag{
219+
Name: "enable-hook",
220+
Aliases: []string{"enable-hooks"},
221+
Usage: "Explicitly enable a hook in the generated CDI specification. This overrides disabled hooks. This can be specified multiple times.",
222+
Destination: &opts.enabledHooks,
223+
Sources: cli.EnvVars("NVIDIA_CTK_CDI_GENERATE_ENABLED_HOOKS"),
224+
},
217225
},
218226
}
219227

@@ -258,6 +266,12 @@ func (m command) validateFlags(c *cli.Command, opts *options) error {
258266
if err := cdi.ValidateClassName(opts.class); err != nil {
259267
return fmt.Errorf("invalid CDI class name: %v", err)
260268
}
269+
270+
for _, hook := range opts.enabledHooks {
271+
if hook == "all" {
272+
return fmt.Errorf("enabling all hooks is not supported")
273+
}
274+
}
261275
return nil
262276
}
263277

@@ -313,14 +327,12 @@ func (m command) generateSpec(opts *options) (spec.Interface, error) {
313327
nvcdi.WithLibrarySearchPaths(opts.librarySearchPaths),
314328
nvcdi.WithCSVFiles(opts.csv.files),
315329
nvcdi.WithCSVIgnorePatterns(opts.csv.ignorePatterns),
330+
nvcdi.WithDisabledHooks(opts.disabledHooks...),
331+
nvcdi.WithEnabledHooks(opts.enabledHooks...),
316332
// We set the following to allow for dependency injection:
317333
nvcdi.WithNvmlLib(opts.nvmllib),
318334
}
319335

320-
for _, hook := range opts.disabledHooks {
321-
cdiOptions = append(cdiOptions, nvcdi.WithDisabledHook(hook))
322-
}
323-
324336
cdilib, err := nvcdi.New(cdiOptions...)
325337
if err != nil {
326338
return nil, fmt.Errorf("failed to create CDI library: %v", err)

cmd/nvidia-ctk/cdi/generate/generate_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,91 @@ containerEdits:
359359
- nodev
360360
- rbind
361361
- rprivate
362+
`,
363+
},
364+
{
365+
description: "enableChmodHook",
366+
options: options{
367+
format: "yaml",
368+
mode: "management",
369+
vendor: "example.com",
370+
class: "device",
371+
driverRoot: driverRoot,
372+
enabledHooks: []string{"chmod"},
373+
disabledHooks: []string{"enable-cuda-compat", "update-ldcache", "disable-device-node-modification"},
374+
},
375+
expectedOptions: options{
376+
format: "yaml",
377+
mode: "management",
378+
vendor: "example.com",
379+
class: "device",
380+
nvidiaCDIHookPath: "/usr/bin/nvidia-cdi-hook",
381+
driverRoot: driverRoot,
382+
enabledHooks: []string{"chmod"},
383+
disabledHooks: []string{"enable-cuda-compat", "update-ldcache", "disable-device-node-modification"},
384+
},
385+
expectedSpec: `---
386+
cdiVersion: 0.5.0
387+
kind: example.com/device
388+
devices:
389+
- name: all
390+
containerEdits:
391+
deviceNodes:
392+
- path: /dev/nvidia0
393+
hostPath: {{ .driverRoot }}/dev/nvidia0
394+
- path: /dev/nvidiactl
395+
hostPath: {{ .driverRoot }}/dev/nvidiactl
396+
- path: /dev/nvidia-caps-imex-channels/channel0
397+
hostPath: {{ .driverRoot }}/dev/nvidia-caps-imex-channels/channel0
398+
- path: /dev/nvidia-caps-imex-channels/channel1
399+
hostPath: {{ .driverRoot }}/dev/nvidia-caps-imex-channels/channel1
400+
- path: /dev/nvidia-caps-imex-channels/channel2047
401+
hostPath: {{ .driverRoot }}/dev/nvidia-caps-imex-channels/channel2047
402+
- path: /dev/nvidia-caps/nvidia-cap1
403+
hostPath: {{ .driverRoot }}/dev/nvidia-caps/nvidia-cap1
404+
hooks:
405+
- hookName: createContainer
406+
path: /usr/bin/nvidia-cdi-hook
407+
args:
408+
- nvidia-cdi-hook
409+
- chmod
410+
- --mode
411+
- "755"
412+
- --path
413+
- /dev/nvidia-caps
414+
env:
415+
- NVIDIA_CTK_DEBUG=false
416+
containerEdits:
417+
env:
418+
- NVIDIA_CTK_LIBCUDA_DIR=/lib/x86_64-linux-gnu
419+
- NVIDIA_VISIBLE_DEVICES=void
420+
hooks:
421+
- hookName: createContainer
422+
path: /usr/bin/nvidia-cdi-hook
423+
args:
424+
- nvidia-cdi-hook
425+
- create-symlinks
426+
- --link
427+
- libcuda.so.1::/lib/x86_64-linux-gnu/libcuda.so
428+
env:
429+
- NVIDIA_CTK_DEBUG=false
430+
mounts:
431+
- hostPath: {{ .driverRoot }}/lib/x86_64-linux-gnu/libcuda.so.999.88.77
432+
containerPath: /lib/x86_64-linux-gnu/libcuda.so.999.88.77
433+
options:
434+
- ro
435+
- nosuid
436+
- nodev
437+
- rbind
438+
- rprivate
439+
- hostPath: {{ .driverRoot }}/lib/x86_64-linux-gnu/vdpau/libvdpau_nvidia.so.999.88.77
440+
containerPath: /lib/x86_64-linux-gnu/vdpau/libvdpau_nvidia.so.999.88.77
441+
options:
442+
- ro
443+
- nosuid
444+
- nodev
445+
- rbind
446+
- rprivate
362447
`,
363448
},
364449
}

internal/discover/hooks.go

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ const (
5050
defaultNvidiaCDIHookPath = "/usr/bin/nvidia-cdi-hook"
5151
)
5252

53+
// defaultDisabledHooks defines hooks that are disabled by default.
54+
// These hooks can be explicitly enabled using the WithEnabledHooks option.
55+
var defaultDisabledHooks = []HookName{
56+
// ChmodHook is disabled by default as it was a workaround for older
57+
// versions of crun that has since been fixed.
58+
ChmodHook,
59+
}
60+
5361
var _ Discover = (*Hook)(nil)
5462

5563
// Devices returns an empty list of devices for a Hook discoverer.
@@ -77,7 +85,14 @@ func (h *Hook) Hooks() ([]Hook, error) {
7785
return []Hook{*h}, nil
7886
}
7987

80-
type Option func(*cdiHookCreator)
88+
type hookCreatorOptions struct {
89+
nvidiaCDIHookPath string
90+
disabledHooks []HookName
91+
enabledHooks []HookName
92+
debugLogging bool
93+
}
94+
95+
type Option func(*hookCreatorOptions)
8196

8297
type cdiHookCreator struct {
8398
nvidiaCDIHookPath string
@@ -100,39 +115,66 @@ type HookCreator interface {
100115
Create(HookName, ...string) *Hook
101116
}
102117

103-
// WithDisabledHooks sets the set of hooks that are disabled for the CDI hook creator.
118+
func WithDebugLogging(debugLogging bool) Option {
119+
return func(hco *hookCreatorOptions) {
120+
hco.debugLogging = debugLogging
121+
}
122+
}
123+
124+
// WithDisabledHooks explicitly disables the specified hooks.
104125
// This can be specified multiple times.
105126
func WithDisabledHooks(hooks ...HookName) Option {
106-
return func(c *cdiHookCreator) {
107-
for _, hook := range hooks {
108-
c.disabledHooks[hook] = true
109-
}
127+
return func(c *hookCreatorOptions) {
128+
c.disabledHooks = append(c.disabledHooks, hooks...)
129+
}
130+
}
131+
132+
// WithEnabledHooks explicitly enables the specified hooks.
133+
// This is useful for enabling hooks that are disabled by default.
134+
func WithEnabledHooks(hooks ...HookName) Option {
135+
return func(c *hookCreatorOptions) {
136+
c.enabledHooks = append(c.enabledHooks, hooks...)
110137
}
111138
}
112139

113140
// WithNVIDIACDIHookPath sets the path to the nvidia-cdi-hook binary.
114141
func WithNVIDIACDIHookPath(nvidiaCDIHookPath string) Option {
115-
return func(c *cdiHookCreator) {
142+
return func(c *hookCreatorOptions) {
116143
c.nvidiaCDIHookPath = nvidiaCDIHookPath
117144
}
118145
}
119146

120147
func NewHookCreator(opts ...Option) HookCreator {
121-
cdiHookCreator := &cdiHookCreator{
148+
o := &hookCreatorOptions{
122149
nvidiaCDIHookPath: defaultNvidiaCDIHookPath,
123-
disabledHooks: make(map[HookName]bool),
124150
}
125151
for _, opt := range opts {
126-
opt(cdiHookCreator)
152+
opt(o)
127153
}
128154

129-
if cdiHookCreator.disabledHooks[AllHooks] {
155+
o.disabledHooks = append(o.disabledHooks, defaultDisabledHooks...)
156+
157+
disabledHooks := make(map[HookName]bool)
158+
for _, h := range o.disabledHooks {
159+
disabledHooks[h] = true
160+
}
161+
162+
if disabledHooks[AllHooks] && len(o.enabledHooks) == 0 {
130163
return &allDisabledHookCreator{}
131164
}
132165

133-
cdiHookCreator.fixedArgs = getFixedArgsForCDIHookCLI(cdiHookCreator.nvidiaCDIHookPath)
166+
for _, h := range o.enabledHooks {
167+
disabledHooks[h] = false
168+
}
169+
170+
c := &cdiHookCreator{
171+
nvidiaCDIHookPath: o.nvidiaCDIHookPath,
172+
disabledHooks: disabledHooks,
173+
fixedArgs: getFixedArgsForCDIHookCLI(o.nvidiaCDIHookPath),
174+
debugLogging: o.debugLogging,
175+
}
134176

135-
return cdiHookCreator
177+
return c
136178
}
137179

138180
// Create creates a new hook with the given name and arguments.
@@ -150,21 +192,19 @@ func (c cdiHookCreator) Create(name HookName, args ...string) *Hook {
150192
}
151193
}
152194

153-
// isDisabled checks if the specified hook name is disabled.
154195
func (c cdiHookCreator) isDisabled(name HookName, args ...string) bool {
155-
if c.disabledHooks[name] {
196+
disabled, ok := c.disabledHooks[name]
197+
if ok {
198+
return disabled
199+
}
200+
if c.disabledHooks[AllHooks] {
156201
return true
157202
}
158203

204+
// still reject hooks that require args if none were provided
159205
switch name {
160-
case CreateSymlinksHook:
161-
if len(args) == 0 {
162-
return true
163-
}
164-
case ChmodHook:
165-
if len(args) == 0 {
166-
return true
167-
}
206+
case CreateSymlinksHook, ChmodHook:
207+
return len(args) == 0
168208
}
169209
return false
170210
}

0 commit comments

Comments
 (0)