mountFd creates a "mount source fd" (either through open_tree(2) or just open(O_PATH)) based on the provided configuration. This function must be called from within the container's mount namespace. In the case of idmapped mount configurations, the returned mount source will be an open_tree(2) file
(nsHandles *userns.Handles, m *configs.Mount)
| 251 | // |
| 252 | // This helper is only intended to be used by goCreateMountSources. |
| 253 | func mountFd(nsHandles *userns.Handles, m *configs.Mount) (_ *mountSource, retErr error) { |
| 254 | if !m.IsBind() { |
| 255 | return nil, errors.New("new mount api: only bind-mounts are supported") |
| 256 | } |
| 257 | if nsHandles == nil { |
| 258 | nsHandles = new(userns.Handles) |
| 259 | defer nsHandles.Release() |
| 260 | } |
| 261 | |
| 262 | var mountFile *os.File |
| 263 | var sourceType mountSourceType |
| 264 | defer func() { |
| 265 | if retErr != nil && mountFile != nil { |
| 266 | mountFile.Close() |
| 267 | } |
| 268 | }() |
| 269 | |
| 270 | // Ideally, we would use OPEN_TREE_CLONE for everything, because we can |
| 271 | // be sure that the file descriptor cannot be used to escape outside of |
| 272 | // the mount root. Unfortunately, OPEN_TREE_CLONE is far more expensive |
| 273 | // than open(2) because it requires doing mounts inside a new anonymous |
| 274 | // mount namespace. So we use open(2) for standard bind-mounts, and |
| 275 | // OPEN_TREE_CLONE when we need to set mount attributes here. |
| 276 | // |
| 277 | // While passing open(2)'d paths from the host rootfs isn't exactly the |
| 278 | // safest thing in the world, the files will not survive across |
| 279 | // execve(2) and "runc init" is non-dumpable so it should not be |
| 280 | // possible for a malicious container process to gain access to the |
| 281 | // file descriptors. We also don't do any of this for "runc exec", |
| 282 | // lessening the risk even further. |
| 283 | if m.IsIDMapped() { |
| 284 | flags := uint(unix.OPEN_TREE_CLONE | unix.OPEN_TREE_CLOEXEC) |
| 285 | if m.Flags&unix.MS_REC == unix.MS_REC { |
| 286 | flags |= unix.AT_RECURSIVE |
| 287 | } |
| 288 | fd, err := unix.OpenTree(unix.AT_FDCWD, m.Source, flags) |
| 289 | if err != nil { |
| 290 | return nil, &os.PathError{Op: "open_tree(OPEN_TREE_CLONE)", Path: m.Source, Err: err} |
| 291 | } |
| 292 | mountFile = os.NewFile(uintptr(fd), m.Source) |
| 293 | sourceType = mountSourceOpenTree |
| 294 | |
| 295 | // Configure the id mapping. |
| 296 | var usernsFile *os.File |
| 297 | if m.IDMapping.UserNSPath == "" { |
| 298 | usernsFile, err = nsHandles.Get(userns.Mapping{ |
| 299 | UIDMappings: m.IDMapping.UIDMappings, |
| 300 | GIDMappings: m.IDMapping.GIDMappings, |
| 301 | }) |
| 302 | if err != nil { |
| 303 | return nil, fmt.Errorf("failed to create userns for %s id-mapping: %w", m.Source, err) |
| 304 | } |
| 305 | } else { |
| 306 | usernsFile, err = os.Open(m.IDMapping.UserNSPath) |
| 307 | if err != nil { |
| 308 | return nil, fmt.Errorf("failed to open existing userns for %s id-mapping: %w", m.Source, err) |
| 309 | } |
| 310 | } |
no test coverage detected
searching dependent graphs…