Allow fsgofer to open character files

Closes #7007

PiperOrigin-RevId: 486008125
This commit is contained in:
Fabricio Voznika
2022-11-03 16:54:01 -07:00
committed by gVisor bot
parent 943eb50b0a
commit 22a0b4acb2
6 changed files with 62 additions and 6 deletions
+2 -2
View File
@@ -276,7 +276,7 @@ docker-tests: load-basic $(RUNTIME_BIN)
overlay-tests: load-basic $(RUNTIME_BIN)
@$(call install_runtime,$(RUNTIME),--overlay)
@$(call test_runtime,$(RUNTIME),$(INTEGRATION_TARGETS))
@$(call test_runtime,$(RUNTIME),--test_env=TEST_OVERLAY=true $(INTEGRATION_TARGETS))
.PHONY: overlay-tests
swgso-tests: load-basic $(RUNTIME_BIN)
@@ -286,7 +286,7 @@ swgso-tests: load-basic $(RUNTIME_BIN)
hostnet-tests: load-basic $(RUNTIME_BIN)
@$(call install_runtime,$(RUNTIME),--network=host)
@$(call test_runtime,$(RUNTIME),--test_env=CHECKPOINT=false --test_env=HOSTNET=true $(INTEGRATION_TARGETS))
@$(call test_runtime,$(RUNTIME),--test_env=CHECKPOINT=false --test_env=HOSTNET=true $(INTEGRATION_TARGETS))
.PHONY: hostnet-tests
kvm-tests: load-basic $(RUNTIME_BIN)
+1 -1
View File
@@ -94,7 +94,7 @@ type specialFileFD struct {
func newSpecialFileFD(h handle, mnt *vfs.Mount, d *dentry, flags uint32) (*specialFileFD, error) {
ftype := d.fileType()
seekable := ftype == linux.S_IFREG || ftype == linux.S_IFCHR || ftype == linux.S_IFBLK
haveQueue := (ftype == linux.S_IFIFO || ftype == linux.S_IFSOCK) && h.fd >= 0
haveQueue := (ftype == linux.S_IFIFO || ftype == linux.S_IFSOCK || ftype == linux.S_IFCHR) && h.fd >= 0
fd := &specialFileFD{
handle: h,
isRegularFile: ftype == linux.S_IFREG,
+7
View File
@@ -54,6 +54,8 @@ var (
totalPartitions = flag.Int("total_partitions", IntFromEnv("TOTAL_PARTITIONS", 1), "total number of partitions")
isRunningWithHostNet = flag.Bool("hostnet", BoolFromEnv("HOSTNET", false), "whether test is running with hostnet")
runscPath = flag.String("runsc", os.Getenv("RUNTIME"), "path to runsc binary")
// Note: flag overlay is already taken by runsc.
isRunningWithOverlay = flag.Bool("test-overlay", BoolFromEnv("TEST_OVERLAY", false), "whether test is running with --overlay")
)
// StringFromEnv returns the value of the named environment variable, or `def` if unset/empty.
@@ -119,6 +121,11 @@ func IsRunningWithHostNet() bool {
return *isRunningWithHostNet
}
// IsRunningWithOverlay returns the relevant command line flag.
func IsRunningWithOverlay() bool {
return *isRunningWithOverlay
}
// ImageByName mangles the image name used locally. This depends on the image
// build infrastructure in images/ and tools/vm.
func ImageByName(name string) string {
+2 -2
View File
@@ -320,7 +320,7 @@ func openAnyFile(pathDebug string, fn func(mode int) (*fd.FD, error)) (*fd.FD, b
func checkSupportedFileType(mode uint32, config *Config) error {
switch mode & unix.S_IFMT {
case unix.S_IFREG, unix.S_IFDIR, unix.S_IFLNK:
case unix.S_IFREG, unix.S_IFDIR, unix.S_IFLNK, unix.S_IFCHR:
return nil
case unix.S_IFSOCK:
@@ -450,7 +450,7 @@ func (l *localFile) Open(flags p9.OpenFlags) (*fd.FD, p9.QID, uint32, error) {
// Best effort to donate file to the Sentry (for performance only).
fd = newFDMaybe(newFile)
case unix.S_IFIFO:
case unix.S_IFIFO, unix.S_IFCHR:
// Character devices and pipes can block indefinitely during reads/writes,
// which is not allowed for gofer operations. Ensure that it donates an FD
// back to the caller, so it can wait on the FD when reads/writes return
+1 -1
View File
@@ -427,7 +427,7 @@ func (fd *controlFDLisa) Open(flags uint32) (*lisafs.OpenFD, int, error) {
// Best effort to donate file to the Sentry (for performance only).
hostOpenFD, _ = unix.Dup(openFD.hostFD)
case unix.S_IFIFO:
case unix.S_IFIFO, unix.S_IFCHR:
// Character devices and pipes can block indefinitely during reads/writes,
// which is not allowed for gofer operations. Ensure that it donates an FD
// back to the caller, so it can wait on the FD when reads/writes return
+49
View File
@@ -22,6 +22,7 @@
package integration
import (
"bytes"
"context"
"flag"
"fmt"
@@ -997,3 +998,51 @@ func TestNonSearchableWorkingDirectory(t *testing.T) {
t.Errorf("ls error message not found, want: %q, got: %q", wantErrorMsg, got)
}
}
func TestCharDevice(t *testing.T) {
if testutil.IsRunningWithOverlay() {
t.Skip("files are not available outside the sandbox with overlay.")
}
ctx := context.Background()
d := dockerutil.MakeContainer(ctx, t)
defer d.CleanUp(ctx)
dir, err := os.MkdirTemp(testutil.TmpDir(), "tmp-mount")
if err != nil {
t.Fatalf("MkdirTemp() failed: %v", err)
}
defer os.RemoveAll(dir)
opts := dockerutil.RunOpts{
Image: "basic/alpine",
Mounts: []mount.Mount{
{
Type: mount.TypeBind,
Source: "/dev/zero",
Target: "/test/zero",
},
{
Type: mount.TypeBind,
Source: dir,
Target: "/out",
},
},
}
const size = 1024 * 1024
// `docker logs` encodes the string, making it hard to compare. Write the
// result to a file that is available to the test.
cmd := fmt.Sprintf("head -c %d /test/zero > /out/result", size)
if _, err := d.Run(ctx, opts, "sh", "-c", cmd); err != nil {
t.Fatalf("docker run failed: %v", err)
}
got, err := os.ReadFile(filepath.Join(dir, "result"))
if err != nil {
t.Fatal(err)
}
if want := [size]byte{}; !bytes.Equal(want[:], got) {
t.Errorf("Wrong bytes, want: [all zeros], got: %v", got)
}
}