Skip to content

Commit

Permalink
libcontainer: Add mountFds struct
Browse files Browse the repository at this point in the history
We will need to pass more slices of fds to these functions in future
patches. Let's add a struct that just contains them all, instead of
adding lot of parameters to these functions.

Signed-off-by: Rodrigo Campos <[email protected]>
  • Loading branch information
rata committed Jul 11, 2023
1 parent 0172016 commit 73b6497
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 14 deletions.
19 changes: 14 additions & 5 deletions libcontainer/init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ type network struct {
TempVethPeerName string `json:"temp_veth_peer_name"`
}

type mountFds struct {
// Fds to use as source when mounting
// Size should be the same as container mounts, as it will be paired.
// The value -1 is used when no fd is needed for the mount.
// Can't have a valid fd in the same position that other slices in this struct.
// We need to use only one of these fds on any single mount.
sourceFds []int
}

// initConfig is used for transferring parameters from Exec() to Init()
type initConfig struct {
Args []string `json:"args"`
Expand Down Expand Up @@ -128,7 +137,7 @@ func StartInitialization() (retErr error) {
}

// Get mount files (O_PATH).
mountFds, err := parseMountFds()
mountSrcFds, err := parseFdsFromEnv("_LIBCONTAINER_MOUNT_FDS")
if err != nil {
return err
}
Expand All @@ -148,10 +157,10 @@ func StartInitialization() (retErr error) {
}()

// If init succeeds, it will not return, hence none of the defers will be called.
return containerInit(it, pipe, consoleSocket, fifofd, logPipeFd, mountFds)
return containerInit(it, pipe, consoleSocket, fifofd, logPipeFd, mountFds{sourceFds: mountSrcFds})
}

func containerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd, logFd int, mountFds []int) error {
func containerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd, logFd int, mountFds mountFds) error {
var config *initConfig
if err := json.NewDecoder(pipe).Decode(&config); err != nil {
return err
Expand All @@ -162,8 +171,8 @@ func containerInit(t initType, pipe *os.File, consoleSocket *os.File, fifoFd, lo
switch t {
case initSetns:
// mountFds must be nil in this case. We don't mount while doing runc exec.
if mountFds != nil {
return errors.New("mountFds must be nil; can't mount from exec")
if mountFds.sourceFds != nil {
return errors.New("mount source fds must be nil; can't mount from exec")
}

i := &linuxSetnsInit{
Expand Down
10 changes: 5 additions & 5 deletions libcontainer/rootfs_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ func needsSetupDev(config *configs.Config) bool {
// prepareRootfs sets up the devices, mount points, and filesystems for use
// inside a new mount namespace. It doesn't set anything as ro. You must call
// finalizeRootfs after this function to finish setting up the rootfs.
func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig, mountFds []int) (err error) {
func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig, mountFds mountFds) (err error) {
config := iConfig.Config
if err := prepareRoot(config); err != nil {
return fmt.Errorf("error preparing rootfs: %w", err)
}

if mountFds != nil && len(mountFds) != len(config.Mounts) {
return fmt.Errorf("malformed mountFds slice. Expected size: %v, got: %v. Slice: %v", len(config.Mounts), len(mountFds), mountFds)
if mountFds.sourceFds != nil && len(mountFds.sourceFds) != len(config.Mounts) {
return fmt.Errorf("malformed mountFds slice. Expected size: %v, got: %v. Slice: %v", len(config.Mounts), len(mountFds.sourceFds), mountFds.sourceFds)
}

mountConfig := &mountConfig{
Expand All @@ -84,8 +84,8 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig, mountFds []int) (err
entry := mountEntry{Mount: m}
// Just before the loop we checked that if not empty, len(mountFds) == len(config.Mounts).
// Therefore, we can access mountFds[i] without any concerns.
if mountFds != nil && mountFds[i] != -1 {
entry.srcFD = "/proc/self/fd/" + strconv.Itoa(mountFds[i])
if mountFds.sourceFds != nil && mountFds.sourceFds[i] != -1 {
entry.srcFD = "/proc/self/fd/" + strconv.Itoa(mountFds.sourceFds[i])
}

if err := mountToRootfs(mountConfig, entry); err != nil {
Expand Down
8 changes: 4 additions & 4 deletions libcontainer/standard_init_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type linuxStandardInit struct {
parentPid int
fifoFd int
logFd int
mountFds []int
mountFds mountFds
config *initConfig
}

Expand Down Expand Up @@ -86,15 +86,15 @@ func (l *linuxStandardInit) Init() error {
// initialises the labeling system
selinux.GetEnabled()

// We don't need the mountFds after prepareRootfs() nor if it fails.
// We don't need the mountFds.SourceFds after prepareRootfs() nor if it fails.
err := prepareRootfs(l.pipe, l.config, l.mountFds)
for _, m := range l.mountFds {
for _, m := range l.mountFds.sourceFds {
if m == -1 {
continue
}

if err := unix.Close(m); err != nil {
return fmt.Errorf("Unable to close mountFds fds: %w", err)
return fmt.Errorf("unable to close mount sourceFds: %w", err)
}
}

Expand Down

0 comments on commit 73b6497

Please sign in to comment.