@@ -19,9 +19,11 @@ package ldconfig
1919
2020import (
2121 "fmt"
22+ "log"
2223 "os"
2324 "os/exec"
2425 "path/filepath"
26+ "strconv"
2527 "strings"
2628
2729 "github.com/NVIDIA/nvidia-container-toolkit/internal/config"
@@ -39,6 +41,7 @@ const (
3941type Ldconfig struct {
4042 ldconfigPath string
4143 inRoot string
44+ isRootless bool
4245}
4346
4447// NewRunner creates an exec.Cmd that can be used to run ldconfig.
@@ -47,26 +50,59 @@ func NewRunner(id string, ldconfigPath string, containerRoot string, additionala
4750 id ,
4851 strings .TrimPrefix (config .NormalizeLDConfigPath ("@" + ldconfigPath ), "@" ),
4952 containerRoot ,
53+ fmt .Sprintf ("rootless=%v" , os .Geteuid () != 0 ),
5054 }
5155 args = append (args , additionalargs ... )
5256
5357 return createReexecCommand (args )
5458}
5559
56- // New creates an Ldconfig struct that is used to perform operations on the
57- // ldcache and libraries in a particular root (e.g. a container).
58- func New (ldconfigPath string , inRoot string ) (* Ldconfig , error ) {
59- l := & Ldconfig {
60- ldconfigPath : ldconfigPath ,
61- inRoot : inRoot ,
62- }
60+ // NewFromRunnerArgs creates an Ldconfig struct from the args passed to the Cmd
61+ // above.
62+ // This struct is used to perform operations on the ldcache and libraries in a
63+ // particular root (e.g. a container).
64+ //
65+ // args[0] is the reexec initializer function name
66+ // args[1] is the path of the ldconfig binary on the host
67+ // args[2] is the container root directory
68+ // args[3] is the optional flag indicating whether the container is being run rootless.
69+ // The remaining args are folders where soname symlinks need to be created.
70+ func NewFromArgs (args ... string ) (* Ldconfig , []string , error ) {
71+ // Validate the number of arguments: [program, ldconfigPath, inRoot]
72+ if len (args ) < 4 {
73+ return nil , args , fmt .Errorf ("incorrect arguments: %v" , args )
74+ }
75+
76+ ldconfigPath := args [1 ]
6377 if ldconfigPath == "" {
64- return nil , fmt .Errorf ("an ldconfig path must be specified" )
78+ return nil , args , fmt .Errorf ("an ldconfig path must be specified" )
6579 }
80+
81+ inRoot := args [2 ]
6682 if inRoot == "" || inRoot == "/" {
67- return nil , fmt .Errorf ("ldconfig must be run in the non-system root" )
83+ return nil , args , fmt .Errorf ("ldconfig must be run in the non-system root" )
84+ }
85+
86+ isRootless := false
87+ if len (args ) >= 4 && strings .HasPrefix (args [3 ], "rootless=" ) {
88+ value , err := strconv .ParseBool (strings .TrimPrefix (args [3 ], "rootless=" ))
89+ if err != nil {
90+ return nil , args , err
91+ }
92+ isRootless = value
6893 }
69- return l , nil
94+
95+ remainingArgs := args [3 :]
96+ if isRootless {
97+ remainingArgs = args [4 :]
98+ }
99+
100+ l := & Ldconfig {
101+ ldconfigPath : ldconfigPath ,
102+ inRoot : inRoot ,
103+ isRootless : isRootless ,
104+ }
105+ return l , remainingArgs , nil
70106}
71107
72108// CreateSonameSymlinks uses ldconfig to create the soname symlinks in the
@@ -130,7 +166,10 @@ func (l *Ldconfig) prepareRoot() (string, error) {
130166 // To prevent leaking the parent proc filesystem, we create a new proc mount
131167 // in the specified root.
132168 if err := mountProc (l .inRoot ); err != nil {
133- return "" , fmt .Errorf ("error mounting /proc: %w" , err )
169+ if ! l .isRootless {
170+ return "" , fmt .Errorf ("error mounting /proc: %w" , err )
171+ }
172+ log .Printf ("Ignoring error for rootless container: %v" , err )
134173 }
135174
136175 // We mount the host ldconfig before we pivot root since host paths are not
0 commit comments