Skip to content

Commit 0945ccb

Browse files
committed
Mount special filesystem in chroot runners
This mounts '/proc' and '/sys' in the input root of runners if 'chroot' is enabled. It is done with "at"-syscall semantics in the 'Directory', to avoid side effects. A program-scope mutex is required for unmounting because there is no easy-to-use "unmountat".
1 parent 33a0262 commit 0945ccb

2 files changed

Lines changed: 80 additions & 0 deletions

File tree

pkg/filesystem/lazy_directory.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,21 @@ func (d *lazyDirectory) Apply(arg interface{}) error {
245245
defer underlying.Close()
246246
return underlying.Apply(arg)
247247
}
248+
249+
func (d *lazyDirectory) Mount(mountpoint path.Component, source string, fstype string) error {
250+
underlying, err := d.openUnderlying()
251+
if err != nil {
252+
return err
253+
}
254+
defer underlying.Close()
255+
return underlying.Mount(mountpoint, source, fstype)
256+
}
257+
258+
func (d *lazyDirectory) Unmount(mountpoint path.Component) error {
259+
underlying, err := d.openUnderlying()
260+
if err != nil {
261+
return err
262+
}
263+
defer underlying.Close()
264+
return underlying.Unmount(mountpoint)
265+
}

pkg/runner/local_runner.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package runner
33
import (
44
"context"
55
"errors"
6+
"fmt"
7+
"os"
68
"os/exec"
79
"path/filepath"
10+
"strings"
811

912
"github.com/buildbarn/bb-remote-execution/pkg/proto/runner"
1013
"github.com/buildbarn/bb-storage/pkg/filesystem"
@@ -17,6 +20,21 @@ import (
1720
"google.golang.org/protobuf/types/known/emptypb"
1821
)
1922

23+
// Mount information for the special filesystems
24+
// to mount in the input root when using 'chroot'.
25+
var (
26+
procMountpointComponent = path.MustNewComponent("proc")
27+
sysMountpointComponent = path.MustNewComponent("sys")
28+
mounts = []struct {
29+
mountpoint path.Component
30+
fstype string
31+
source string
32+
} {
33+
{procMountpointComponent, "proc", "/proc"},
34+
{sysMountpointComponent, "sysfs", "/sys"},
35+
}
36+
)
37+
2038
// logFileResolver is an implementation of path.ComponentWalker that is
2139
// used by localRunner.Run() to traverse to the directory of stdout and
2240
// stderr log files, so that they may be opened.
@@ -136,6 +154,42 @@ func (r *localRunner) Run(ctx context.Context, request *runner.RunRequest) (*run
136154
}
137155
cmd.Stdout = stdout
138156

157+
// Mount special filesystems.
158+
requiresSpecialFilesystems := cmd.SysProcAttr != nil && cmd.SysProcAttr.Chroot != ""
159+
var MountRootDirectory filesystem.Directory
160+
161+
if requiresSpecialFilesystems {
162+
var dir filesystem.Directory
163+
dir = r.buildDirectory
164+
// TODO(nils): How to best open the input root `Directory`
165+
// It must be a `localDirectory`, but outer directories can be `lazyDirectory`.
166+
for _, segment := range strings.Split(request.InputRootDirectory, "/") {
167+
component := path.MustNewComponent(segment)
168+
dircloser, err := dir.EnterDirectory(component)
169+
// We want to keep the input root open so we can use its file descriptor.
170+
if segment != "root" {
171+
defer dircloser.Close()
172+
}
173+
174+
dir = dircloser.(filesystem.Directory)
175+
if err != nil {
176+
return nil, fmt.Errorf("Could not enter directory component '%s' in '%#v'", segment, inputRootDirectory)
177+
}
178+
}
179+
MountRootDirectory = dir
180+
181+
for _, mount := range mounts {
182+
err := MountRootDirectory.Mkdir(mount.mountpoint, 0o555)
183+
if err != nil && !os.IsExist(err) {
184+
return nil, util.StatusWrapf(err, "Failed to create mount point: '%#v' in the input root", mount.mountpoint)
185+
}
186+
187+
if err := MountRootDirectory.Mount(mount.mountpoint, mount.source, mount.fstype); err != nil {
188+
return nil, util.StatusWrapf(err, "Failed to mount '%#v' in the input root", mount)
189+
}
190+
}
191+
}
192+
139193
stderr, err := r.openLog(request.StderrPath)
140194
if err != nil {
141195
stdout.Close()
@@ -166,6 +220,14 @@ func (r *localRunner) Run(ctx context.Context, request *runner.RunRequest) (*run
166220
}
167221
}
168222

223+
if requiresSpecialFilesystems {
224+
for _, mount := range mounts {
225+
if err := MountRootDirectory.Unmount(mount.mountpoint); err != nil {
226+
return nil, util.StatusWrapf(err, "Failed to unmount '%#v' in the input root", mount)
227+
}
228+
}
229+
}
230+
169231
// Attach rusage information to the response.
170232
posixResourceUsage, err := anypb.New(getPOSIXResourceUsage(cmd))
171233
if err != nil {

0 commit comments

Comments
 (0)