Skip to content

Commit 0172979

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 70efb72 commit 0172979

File tree

3 files changed

+83
-5
lines changed

3 files changed

+83
-5
lines changed

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/BUILD.bazel

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,31 +29,27 @@ go_library(
2929
"@org_golang_google_protobuf//proto",
3030
"@org_golang_google_protobuf//types/known/anypb",
3131
"@org_golang_google_protobuf//types/known/emptypb",
32+
"@org_golang_x_sys//unix",
3233
] + select({
3334
"@io_bazel_rules_go//go/platform:android": [
3435
"//pkg/proto/resourceusage",
3536
"@org_golang_google_protobuf//types/known/durationpb",
36-
"@org_golang_x_sys//unix",
3737
],
3838
"@io_bazel_rules_go//go/platform:darwin": [
3939
"//pkg/proto/resourceusage",
4040
"@org_golang_google_protobuf//types/known/durationpb",
41-
"@org_golang_x_sys//unix",
4241
],
4342
"@io_bazel_rules_go//go/platform:freebsd": [
4443
"//pkg/proto/resourceusage",
4544
"@org_golang_google_protobuf//types/known/durationpb",
46-
"@org_golang_x_sys//unix",
4745
],
4846
"@io_bazel_rules_go//go/platform:ios": [
4947
"//pkg/proto/resourceusage",
5048
"@org_golang_google_protobuf//types/known/durationpb",
51-
"@org_golang_x_sys//unix",
5249
],
5350
"@io_bazel_rules_go//go/platform:linux": [
5451
"//pkg/proto/resourceusage",
5552
"@org_golang_google_protobuf//types/known/durationpb",
56-
"@org_golang_x_sys//unix",
5753
],
5854
"@io_bazel_rules_go//go/platform:windows": [
5955
"//pkg/proto/resourceusage",

pkg/runner/local_runner.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,38 @@ package runner
33
import (
44
"context"
55
"errors"
6+
"fmt"
67
"os/exec"
78
"path/filepath"
9+
"strings"
810

911
"github.com/buildbarn/bb-remote-execution/pkg/proto/runner"
1012
"github.com/buildbarn/bb-storage/pkg/filesystem"
1113
"github.com/buildbarn/bb-storage/pkg/filesystem/path"
1214
"github.com/buildbarn/bb-storage/pkg/util"
15+
"golang.org/x/sys/unix"
1316

1417
"google.golang.org/grpc/codes"
1518
"google.golang.org/grpc/status"
1619
"google.golang.org/protobuf/types/known/anypb"
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,44 @@ 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 {
184+
if err != unix.EEXIST {
185+
return nil, util.StatusWrapf(err, "Failed to create mount point: '%#v' in the input root", mount.mountpoint)
186+
}
187+
}
188+
189+
if err := MountRootDirectory.Mount(mount.mountpoint, mount.source, mount.fstype); err != nil {
190+
return nil, util.StatusWrapf(err, "Failed to mount '%#v' in the input root", mount)
191+
}
192+
}
193+
}
194+
139195
stderr, err := r.openLog(request.StderrPath)
140196
if err != nil {
141197
stdout.Close()
@@ -166,6 +222,14 @@ func (r *localRunner) Run(ctx context.Context, request *runner.RunRequest) (*run
166222
}
167223
}
168224

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

0 commit comments

Comments
 (0)