mirror of
				https://github.com/NVIDIA/nvidia-container-toolkit
				synced 2025-06-26 18:18:24 +00:00 
			
		
		
		
	[no-relnote] Move root to separate file
Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
		
							parent
							
								
									04e9bf4ac1
								
							
						
					
					
						commit
						9429fbac5f
					
				
							
								
								
									
										46
									
								
								cmd/nvidia-cdi-hook/update-ldcache/container-root.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								cmd/nvidia-cdi-hook/update-ldcache/container-root.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| /** | ||||
| # Copyright (c) 2025, NVIDIA CORPORATION.  All rights reserved. | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| **/ | ||||
| 
 | ||||
| package ldcache | ||||
| 
 | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 
 | ||||
| 	"github.com/moby/sys/symlink" | ||||
| ) | ||||
| 
 | ||||
| // A containerRoot represents the root filesystem of a container.
 | ||||
| type containerRoot string | ||||
| 
 | ||||
| // hasPath checks whether the specified path exists in the root.
 | ||||
| func (r containerRoot) hasPath(path string) bool { | ||||
| 	resolved, err := r.resolve(path) | ||||
| 	if err != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	if _, err := os.Stat(resolved); err != nil && os.IsNotExist(err) { | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // resolve returns the absolute path including root path.
 | ||||
| // Symlinks are resolved, but are guaranteed to resolve in the root.
 | ||||
| func (r containerRoot) resolve(path string) (string, error) { | ||||
| 	absolute := filepath.Clean(filepath.Join(string(r), path)) | ||||
| 	return symlink.FollowSymlinkInScope(absolute, string(r)) | ||||
| } | ||||
| @ -31,6 +31,15 @@ import ( | ||||
| 	"github.com/NVIDIA/nvidia-container-toolkit/internal/oci" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// ldsoconfdFilenamePattern specifies the pattern for the filename
 | ||||
| 	// in ld.so.conf.d that includes references to the specified directories.
 | ||||
| 	// The 00-nvcr prefix is chosen to ensure that these libraries have a
 | ||||
| 	// higher precedence than other libraries on the system, but lower than
 | ||||
| 	// the 00-cuda-compat that is included in some containers.
 | ||||
| 	ldsoconfdFilenamePattern = "00-nvcr-*.conf" | ||||
| ) | ||||
| 
 | ||||
| type command struct { | ||||
| 	logger logger.Interface | ||||
| } | ||||
| @ -100,18 +109,20 @@ func (m command) run(c *cli.Context, cfg *options) error { | ||||
| 		return fmt.Errorf("failed to load container state: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	containerRoot, err := s.GetContainerRoot() | ||||
| 	containerRootDir, err := s.GetContainerRoot() | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to determined container root: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	ldconfigPath := m.resolveLDConfigPath(cfg.ldconfigPath) | ||||
| 	args := []string{filepath.Base(ldconfigPath)} | ||||
| 	if containerRoot != "" { | ||||
| 		args = append(args, "-r", containerRoot) | ||||
| 	if containerRootDir != "" { | ||||
| 		args = append(args, "-r", containerRootDir) | ||||
| 	} | ||||
| 
 | ||||
| 	if root(containerRoot).hasPath("/etc/ld.so.cache") { | ||||
| 	containerRoot := containerRoot(containerRootDir) | ||||
| 
 | ||||
| 	if containerRoot.hasPath("/etc/ld.so.cache") { | ||||
| 		args = append(args, "-C", "/etc/ld.so.cache") | ||||
| 	} else { | ||||
| 		m.logger.Debugf("No ld.so.cache found, skipping update") | ||||
| @ -119,8 +130,8 @@ func (m command) run(c *cli.Context, cfg *options) error { | ||||
| 	} | ||||
| 
 | ||||
| 	folders := cfg.folders.Value() | ||||
| 	if root(containerRoot).hasPath("/etc/ld.so.conf.d") { | ||||
| 		err := m.createConfig(containerRoot, folders) | ||||
| 	if containerRoot.hasPath("/etc/ld.so.conf.d") { | ||||
| 		err := m.createLdsoconfdFile(containerRoot, ldsoconfdFilenamePattern, folders...) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to update ld.so.conf.d: %v", err) | ||||
| 		} | ||||
| @ -136,16 +147,6 @@ func (m command) run(c *cli.Context, cfg *options) error { | ||||
| 	return syscall.Exec(ldconfigPath, args, nil) | ||||
| } | ||||
| 
 | ||||
| type root string | ||||
| 
 | ||||
| func (r root) hasPath(path string) bool { | ||||
| 	_, err := os.Stat(filepath.Join(string(r), path)) | ||||
| 	if err != nil && os.IsNotExist(err) { | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // resolveLDConfigPath determines the LDConfig path to use for the system.
 | ||||
| // On systems such as Ubuntu where `/sbin/ldconfig` is a wrapper around
 | ||||
| // /sbin/ldconfig.real, the latter is returned.
 | ||||
| @ -153,44 +154,46 @@ func (m command) resolveLDConfigPath(path string) string { | ||||
| 	return strings.TrimPrefix(config.NormalizeLDConfigPath("@"+path), "@") | ||||
| } | ||||
| 
 | ||||
| // createConfig creates (or updates) /etc/ld.so.conf.d/00-nvcr-<RANDOM_STRING>.conf in the container
 | ||||
| // to include the required paths.
 | ||||
| // Note that the 00-nvcr prefix is chosen to ensure that these libraries have
 | ||||
| // a higher precedence than other libraries on the system but are applied AFTER
 | ||||
| // 00-cuda-compat.conf.
 | ||||
| func (m command) createConfig(root string, folders []string) error { | ||||
| 	if len(folders) == 0 { | ||||
| 		m.logger.Debugf("No folders to add to /etc/ld.so.conf") | ||||
| // createLdsoconfdFile creates a file at /etc/ld.so.conf.d/ in the specified root.
 | ||||
| // The file is created at /etc/ld.so.conf.d/{{ .pattern }} using `CreateTemp` and
 | ||||
| // contains the specified directories on each line.
 | ||||
| func (m command) createLdsoconfdFile(in containerRoot, pattern string, dirs ...string) error { | ||||
| 	if len(dirs) == 0 { | ||||
| 		m.logger.Debugf("No directories to add to /etc/ld.so.conf") | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if err := os.MkdirAll(filepath.Join(root, "/etc/ld.so.conf.d"), 0755); err != nil { | ||||
| 		return fmt.Errorf("failed to create ld.so.conf.d: %v", err) | ||||
| 	ldsoconfdDir, err := in.resolve("/etc/ld.so.conf.d") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := os.MkdirAll(ldsoconfdDir, 0755); err != nil { | ||||
| 		return fmt.Errorf("failed to create ld.so.conf.d: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	configFile, err := os.CreateTemp(filepath.Join(root, "/etc/ld.so.conf.d"), "00-nvcr-*.conf") | ||||
| 	configFile, err := os.CreateTemp(ldsoconfdDir, pattern) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("failed to create config file: %v", err) | ||||
| 		return fmt.Errorf("failed to create config file: %w", err) | ||||
| 	} | ||||
| 	defer configFile.Close() | ||||
| 
 | ||||
| 	m.logger.Debugf("Adding folders %v to %v", folders, configFile.Name()) | ||||
| 	m.logger.Debugf("Adding directories %v to %v", dirs, configFile.Name()) | ||||
| 
 | ||||
| 	configured := make(map[string]bool) | ||||
| 	for _, folder := range folders { | ||||
| 		if configured[folder] { | ||||
| 	added := make(map[string]bool) | ||||
| 	for _, dir := range dirs { | ||||
| 		if added[dir] { | ||||
| 			continue | ||||
| 		} | ||||
| 		_, err = configFile.WriteString(fmt.Sprintf("%s\n", folder)) | ||||
| 		_, err = configFile.WriteString(fmt.Sprintf("%s\n", dir)) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failed to update ld.so.conf.d: %v", err) | ||||
| 			return fmt.Errorf("failed to update config file: %w", err) | ||||
| 		} | ||||
| 		configured[folder] = true | ||||
| 		added[dir] = true | ||||
| 	} | ||||
| 
 | ||||
| 	// The created file needs to be world readable for the cases where the container is run as a non-root user.
 | ||||
| 	if err := os.Chmod(configFile.Name(), 0644); err != nil { | ||||
| 		return fmt.Errorf("failed to chmod config file: %v", err) | ||||
| 	if err := configFile.Chmod(0644); err != nil { | ||||
| 		return fmt.Errorf("failed to chmod config file: %w", err) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user