20
20
package disabledevicenodemodification
21
21
22
22
import (
23
+ "errors"
23
24
"fmt"
24
25
"os"
25
26
"path/filepath"
26
27
28
+ securejoin "github.com/cyphar/filepath-securejoin"
27
29
"github.com/opencontainers/runc/libcontainer/utils"
28
30
"golang.org/x/sys/unix"
29
31
)
30
32
31
33
func createParamsFileInContainer (containerRootDirPath string , contents []byte ) error {
32
- tmpRoot , err := os . MkdirTemp ( "" , "nvct-empty-dir*" )
33
- if err != nil {
34
- return fmt .Errorf ("failed to create temp root : %w" , err )
34
+ hookScratchDirPath := "/var/run/nvidia-ctk-hook"
35
+ if err := utils . MkdirAllInRoot ( containerRootDirPath , hookScratchDirPath , 0755 ); err != nil {
36
+ return fmt .Errorf ("error creating hook scratch folder : %w" , err )
35
37
}
36
38
37
- if err := createTmpFs (tmpRoot , len (contents )); err != nil {
38
- return fmt .Errorf ("failed to create tmpfs mount for params file: %w" , err )
39
- }
39
+ err := utils .WithProcfd (containerRootDirPath , hookScratchDirPath , func (hookScratchDirFdPath string ) error {
40
+ return createTmpFs (hookScratchDirFdPath , len (contents ))
40
41
41
- modifiedParamsFile , err := os . OpenFile ( filepath . Join ( tmpRoot , "nvct-params" ), os . O_WRONLY | os . O_CREATE | os . O_TRUNC , 0444 )
42
+ } )
42
43
if err != nil {
43
- return fmt .Errorf ("failed to open modified params file: %w" , err )
44
+ return fmt .Errorf ("failed to create tmpfs mount for params file: %w" , err )
44
45
}
45
- defer modifiedParamsFile .Close ()
46
46
47
- if _ , err := modifiedParamsFile .Write (contents ); err != nil {
48
- return fmt .Errorf ("failed to write temporary params file: %w" , err )
47
+ modifiedParamsFilePath := filepath .Join (hookScratchDirPath , "nvct-params" )
48
+ if _ , err := createFileInRoot (containerRootDirPath , modifiedParamsFilePath , 0444 ); err != nil {
49
+ return fmt .Errorf ("error creating modified params file: %w" , err )
49
50
}
50
51
51
- err = utils .WithProcfd (containerRootDirPath , nvidiaDriverParamsPath , func (nvidiaDriverParamsFdPath string ) error {
52
- return unix .Mount (modifiedParamsFile .Name (), nvidiaDriverParamsFdPath , "" , unix .MS_BIND | unix .MS_RDONLY | unix .MS_NODEV | unix .MS_PRIVATE | unix .MS_NOSYMFOLLOW , "" )
52
+ err = utils .WithProcfd (containerRootDirPath , modifiedParamsFilePath , func (modifiedParamsFileFdPath string ) error {
53
+ modifiedParamsFile , err := os .OpenFile (modifiedParamsFileFdPath , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , 0444 )
54
+ if err != nil {
55
+ return fmt .Errorf ("failed to open modified params file: %w" , err )
56
+ }
57
+ defer modifiedParamsFile .Close ()
58
+
59
+ if _ , err := modifiedParamsFile .Write (contents ); err != nil {
60
+ return fmt .Errorf ("failed to write temporary params file: %w" , err )
61
+ }
62
+
63
+ err = utils .WithProcfd (containerRootDirPath , nvidiaDriverParamsPath , func (nvidiaDriverParamsFdPath string ) error {
64
+ return unix .Mount (modifiedParamsFileFdPath , nvidiaDriverParamsFdPath , "" , unix .MS_BIND | unix .MS_RDONLY | unix .MS_NODEV | unix .MS_PRIVATE | unix .MS_NOSYMFOLLOW , "" )
65
+ })
66
+ if err != nil {
67
+ return fmt .Errorf ("failed to mount modified params file: %w" , err )
68
+ }
69
+
70
+ return nil
53
71
})
54
72
if err != nil {
55
- return fmt . Errorf ( "failed to mount modified params file: %w" , err )
73
+ return err
56
74
}
57
75
58
76
return nil
@@ -61,3 +79,32 @@ func createParamsFileInContainer(containerRootDirPath string, contents []byte) e
61
79
func createTmpFs (target string , size int ) error {
62
80
return unix .Mount ("tmpfs" , target , "tmpfs" , 0 , fmt .Sprintf ("size=%d" , size ))
63
81
}
82
+
83
+ // TODO(ArangoGutierrez): This function also exists in internal/ldconfig we should move this to a separate package.
84
+ func createFileInRoot (containerRootDirPath string , destinationPath string , mode os.FileMode ) (string , error ) {
85
+ dest , err := securejoin .SecureJoin (containerRootDirPath , destinationPath )
86
+ if err != nil {
87
+ return "" , err
88
+ }
89
+ // Make the parent directory.
90
+ destDir , destBase := filepath .Split (dest )
91
+ destDirFd , err := utils .MkdirAllInRootOpen (containerRootDirPath , destDir , 0755 )
92
+ if err != nil {
93
+ return "" , fmt .Errorf ("error creating parent dir: %w" , err )
94
+ }
95
+ defer destDirFd .Close ()
96
+ // Make the target file. We want to avoid opening any file that is
97
+ // already there because it could be a "bad" file like an invalid
98
+ // device or hung tty that might cause a DoS, so we use mknodat.
99
+ // destBase does not contain any "/" components, and mknodat does
100
+ // not follow trailing symlinks, so we can safely just call mknodat
101
+ // here.
102
+ if err := unix .Mknodat (int (destDirFd .Fd ()), destBase , unix .S_IFREG | uint32 (mode ), 0 ); err != nil {
103
+ // If we get EEXIST, there was already an inode there and
104
+ // we can consider that a success.
105
+ if ! errors .Is (err , unix .EEXIST ) {
106
+ return "" , fmt .Errorf ("error creating empty file: %w" , err )
107
+ }
108
+ }
109
+ return dest , nil
110
+ }
0 commit comments