summaryrefslogtreecommitdiffhomepage
path: root/runsc/boot
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/boot')
-rw-r--r--runsc/boot/compat.go8
-rw-r--r--runsc/boot/compat_amd64.go22
-rw-r--r--runsc/boot/compat_arm64.go22
-rw-r--r--runsc/boot/fs.go22
-rw-r--r--runsc/boot/vfs.go90
5 files changed, 128 insertions, 36 deletions
diff --git a/runsc/boot/compat.go b/runsc/boot/compat.go
index b7cfb35bf..84c67cbc2 100644
--- a/runsc/boot/compat.go
+++ b/runsc/boot/compat.go
@@ -119,7 +119,13 @@ func (c *compatEmitter) emitUnimplementedSyscall(us *spb.UnimplementedSyscall) {
}
if tr.shouldReport(regs) {
- c.sink.Infof("Unsupported syscall: %s, regs: %+v", c.nameMap.Name(uintptr(sysnr)), regs)
+ name := c.nameMap.Name(uintptr(sysnr))
+ c.sink.Infof("Unsupported syscall %s(%#x,%#x,%#x,%#x,%#x,%#x). It is "+
+ "likely that you can safely ignore this message and that this is not "+
+ "the cause of any error. Please, refer to %s/%s for more information.",
+ name, argVal(0, regs), argVal(1, regs), argVal(2, regs), argVal(3, regs),
+ argVal(4, regs), argVal(5, regs), syscallLink, name)
+
tr.onReported(regs)
}
}
diff --git a/runsc/boot/compat_amd64.go b/runsc/boot/compat_amd64.go
index 42b0ca8b0..8eb76b2ba 100644
--- a/runsc/boot/compat_amd64.go
+++ b/runsc/boot/compat_amd64.go
@@ -24,8 +24,12 @@ import (
"gvisor.dev/gvisor/pkg/sentry/strace"
)
-// reportLimit is the max number of events that should be reported per tracker.
-const reportLimit = 100
+const (
+ // reportLimit is the max number of events that should be reported per
+ // tracker.
+ reportLimit = 100
+ syscallLink = "https://gvisor.dev/c/linux/amd64"
+)
// newRegs create a empty Registers instance.
func newRegs() *rpb.Registers {
@@ -36,22 +40,22 @@ func newRegs() *rpb.Registers {
}
}
-func argVal(argIdx int, regs *rpb.Registers) uint32 {
+func argVal(argIdx int, regs *rpb.Registers) uint64 {
amd64Regs := regs.GetArch().(*rpb.Registers_Amd64).Amd64
switch argIdx {
case 0:
- return uint32(amd64Regs.Rdi)
+ return amd64Regs.Rdi
case 1:
- return uint32(amd64Regs.Rsi)
+ return amd64Regs.Rsi
case 2:
- return uint32(amd64Regs.Rdx)
+ return amd64Regs.Rdx
case 3:
- return uint32(amd64Regs.R10)
+ return amd64Regs.R10
case 4:
- return uint32(amd64Regs.R8)
+ return amd64Regs.R8
case 5:
- return uint32(amd64Regs.R9)
+ return amd64Regs.R9
}
panic(fmt.Sprintf("invalid syscall argument index %d", argIdx))
}
diff --git a/runsc/boot/compat_arm64.go b/runsc/boot/compat_arm64.go
index f784cd237..bce9d95b3 100644
--- a/runsc/boot/compat_arm64.go
+++ b/runsc/boot/compat_arm64.go
@@ -23,8 +23,12 @@ import (
"gvisor.dev/gvisor/pkg/sentry/strace"
)
-// reportLimit is the max number of events that should be reported per tracker.
-const reportLimit = 100
+const (
+ // reportLimit is the max number of events that should be reported per
+ // tracker.
+ reportLimit = 100
+ syscallLink = "https://gvisor.dev/c/linux/arm64"
+)
// newRegs create a empty Registers instance.
func newRegs() *rpb.Registers {
@@ -35,22 +39,22 @@ func newRegs() *rpb.Registers {
}
}
-func argVal(argIdx int, regs *rpb.Registers) uint32 {
+func argVal(argIdx int, regs *rpb.Registers) uint64 {
arm64Regs := regs.GetArch().(*rpb.Registers_Arm64).Arm64
switch argIdx {
case 0:
- return uint32(arm64Regs.R0)
+ return arm64Regs.R0
case 1:
- return uint32(arm64Regs.R1)
+ return arm64Regs.R1
case 2:
- return uint32(arm64Regs.R2)
+ return arm64Regs.R2
case 3:
- return uint32(arm64Regs.R3)
+ return arm64Regs.R3
case 4:
- return uint32(arm64Regs.R4)
+ return arm64Regs.R4
case 5:
- return uint32(arm64Regs.R5)
+ return arm64Regs.R5
}
panic(fmt.Sprintf("invalid syscall argument index %d", argIdx))
}
diff --git a/runsc/boot/fs.go b/runsc/boot/fs.go
index 8df5cc989..e1181271a 100644
--- a/runsc/boot/fs.go
+++ b/runsc/boot/fs.go
@@ -770,14 +770,8 @@ func (c *containerMounter) getMountNameAndOptions(conf *Config, m specs.Mount) (
useOverlay bool
)
- for _, opt := range m.Options {
- // When options include either "bind" or "rbind", this behaves as
- // bind mount even if the mount type is equal to a filesystem supported
- // on runsc.
- if opt == "bind" || opt == "rbind" {
- m.Type = bind
- break
- }
+ if isBindMount(m) {
+ m.Type = bind
}
switch m.Type {
@@ -807,6 +801,18 @@ func (c *containerMounter) getMountNameAndOptions(conf *Config, m specs.Mount) (
return fsName, opts, useOverlay, nil
}
+func isBindMount(m specs.Mount) bool {
+ for _, opt := range m.Options {
+ // When options include either "bind" or "rbind", this behaves as
+ // bind mount even if the mount type is equal to a filesystem supported
+ // on runsc.
+ if opt == "bind" || opt == "rbind" {
+ return true
+ }
+ }
+ return false
+}
+
func (c *containerMounter) getMountAccessType(mount specs.Mount) FileAccessType {
if hint := c.hints.findMount(mount); hint != nil {
return hint.fileAccessType()
diff --git a/runsc/boot/vfs.go b/runsc/boot/vfs.go
index 7378fbc95..147c901c4 100644
--- a/runsc/boot/vfs.go
+++ b/runsc/boot/vfs.go
@@ -203,28 +203,61 @@ func (c *containerMounter) createMountNamespaceVFS2(ctx context.Context, conf *C
}
func (c *containerMounter) mountSubmountsVFS2(ctx context.Context, conf *Config, mns *vfs.MountNamespace, creds *auth.Credentials) error {
- c.prepareMountsVFS2()
+ mounts, err := c.prepareMountsVFS2()
+ if err != nil {
+ return err
+ }
- for _, submount := range c.mounts {
+ for i := range mounts {
+ submount := &mounts[i]
log.Debugf("Mounting %q to %q, type: %s, options: %s", submount.Source, submount.Destination, submount.Type, submount.Options)
- if err := c.mountSubmountVFS2(ctx, conf, mns, creds, &submount); err != nil {
+ if err := c.mountSubmountVFS2(ctx, conf, mns, creds, submount); err != nil {
return err
}
}
// TODO(gvisor.dev/issue/1487): implement mountTmp from fs.go.
- return c.checkDispenser()
+ return nil
+}
+
+type mountAndFD struct {
+ specs.Mount
+ fd int
}
-func (c *containerMounter) prepareMountsVFS2() {
+func (c *containerMounter) prepareMountsVFS2() ([]mountAndFD, error) {
+ // Associate bind mounts with their FDs before sorting since there is an
+ // undocumented assumption that FDs are dispensed in the order in which
+ // they are required by mounts.
+ var mounts []mountAndFD
+ for _, m := range c.mounts {
+ fd := -1
+ // Only bind mounts use host FDs; see
+ // containerMounter.getMountNameAndOptionsVFS2.
+ if m.Type == bind || isBindMount(m) {
+ fd = c.fds.remove()
+ }
+ mounts = append(mounts, mountAndFD{
+ Mount: m,
+ fd: fd,
+ })
+ }
+ if err := c.checkDispenser(); err != nil {
+ return nil, err
+ }
+
// Sort the mounts so that we don't place children before parents.
- sort.Slice(c.mounts, func(i, j int) bool { return len(c.mounts[i].Destination) < len(c.mounts[j].Destination) })
+ sort.Slice(mounts, func(i, j int) bool {
+ return len(mounts[i].Destination) < len(mounts[j].Destination)
+ })
+
+ return mounts, nil
}
// TODO(gvisor.dev/issue/1487): Implement submount options similar to the VFS1
-// version.
-func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config, mns *vfs.MountNamespace, creds *auth.Credentials, submount *specs.Mount) error {
+// version.
+func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config, mns *vfs.MountNamespace, creds *auth.Credentials, submount *mountAndFD) error {
root := mns.Root()
defer root.DecRef()
target := &vfs.PathOperation{
@@ -233,7 +266,7 @@ func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config,
Path: fspath.Parse(submount.Destination),
}
- fsName, options, useOverlay, err := c.getMountNameAndOptions(conf, *submount)
+ fsName, options, useOverlay, err := c.getMountNameAndOptionsVFS2(conf, submount)
if err != nil {
return fmt.Errorf("mountOptions failed: %w", err)
}
@@ -263,6 +296,45 @@ func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config,
return nil
}
+// getMountNameAndOptionsVFS2 retrieves the fsName, opts, and useOverlay values
+// used for mounts.
+func (c *containerMounter) getMountNameAndOptionsVFS2(conf *Config, m *mountAndFD) (string, []string, bool, error) {
+ var (
+ fsName string
+ opts []string
+ useOverlay bool
+ )
+
+ if isBindMount(m.Mount) {
+ m.Type = bind
+ }
+
+ switch m.Type {
+ case devpts.Name, devtmpfs.Name, proc.Name, sys.Name:
+ fsName = m.Type
+ case nonefs:
+ fsName = sys.Name
+ case tmpfs.Name:
+ fsName = m.Type
+
+ var err error
+ opts, err = parseAndFilterOptions(m.Options, tmpfsAllowedOptions...)
+ if err != nil {
+ return "", nil, false, err
+ }
+
+ case bind:
+ fsName = gofer.Name
+ opts = p9MountOptions(m.fd, c.getMountAccessType(m.Mount), true /* vfs2 */)
+ // If configured, add overlay to all writable mounts.
+ useOverlay = conf.Overlay && !mountFlags(m.Options).ReadOnly
+
+ default:
+ log.Warningf("ignoring unknown filesystem type %q", m.Type)
+ }
+ return fsName, opts, useOverlay, nil
+}
+
func (c *containerMounter) makeSyntheticMount(ctx context.Context, currentPath string, root vfs.VirtualDentry, creds *auth.Credentials) error {
target := &vfs.PathOperation{
Root: root,