Add friendlier messages for frequently encountered errors.

Issue #2270
Issue #1765

PiperOrigin-RevId: 305385436
This commit is contained in:
Ian Lewis
2020-04-07 18:51:01 -07:00
committed by gVisor bot
parent 5802051b3d
commit 56054fc1fb
3 changed files with 75 additions and 3 deletions
+14 -1
View File
@@ -824,7 +824,20 @@ func (c *containerMounter) mountSubmount(ctx context.Context, conf *Config, mns
inode, err := filesystem.Mount(ctx, mountDevice(m), mf, strings.Join(opts, ","), nil)
if err != nil {
return fmt.Errorf("creating mount with source %q: %v", m.Source, err)
err := fmt.Errorf("creating mount with source %q: %v", m.Source, err)
// Check to see if this is a common error due to a Linux bug.
// This error is generated here in order to cause it to be
// printed to the user using Docker via 'runsc create' etc. rather
// than simply printed to the logs for the 'runsc boot' command.
//
// We check the error message string rather than type because the
// actual error types (syscall.EIO, syscall.EPIPE) are lost by file system
// implementation (e.g. p9).
// TODO(gvisor.dev/issue/1765): Remove message when bug is resolved.
if strings.Contains(err.Error(), syscall.EIO.Error()) || strings.Contains(err.Error(), syscall.EPIPE.Error()) {
return fmt.Errorf("%v: %s", err, specutils.FaqErrorMsg("memlock", "you may be encountering a Linux kernel bug"))
}
return err
}
// If there are submounts, we need to overlay the mount on top of a ramfs
+56 -2
View File
@@ -18,10 +18,12 @@ package sandbox
import (
"context"
"fmt"
"io"
"math"
"os"
"os/exec"
"strconv"
"strings"
"syscall"
"time"
@@ -142,7 +144,19 @@ func New(conf *boot.Config, args *Args) (*Sandbox, error) {
// Wait until the sandbox has booted.
b := make([]byte, 1)
if l, err := clientSyncFile.Read(b); err != nil || l != 1 {
return nil, fmt.Errorf("waiting for sandbox to start: %v", err)
err := fmt.Errorf("waiting for sandbox to start: %v", err)
// If the sandbox failed to start, it may be because the binary
// permissions were incorrect. Check the bits and return a more helpful
// error message.
//
// NOTE: The error message is checked because error types are lost over
// rpc calls.
if strings.Contains(err.Error(), io.EOF.Error()) {
if permsErr := checkBinaryPermissions(conf); permsErr != nil {
return nil, fmt.Errorf("%v: %v", err, permsErr)
}
}
return nil, err
}
c.Release()
@@ -706,7 +720,19 @@ func (s *Sandbox) createSandboxProcess(conf *boot.Config, args *Args, startSyncF
log.Debugf("Starting sandbox: %s %v", binPath, cmd.Args)
log.Debugf("SysProcAttr: %+v", cmd.SysProcAttr)
if err := specutils.StartInNS(cmd, nss); err != nil {
return fmt.Errorf("Sandbox: %v", err)
err := fmt.Errorf("starting sandbox: %v", err)
// If the sandbox failed to start, it may be because the binary
// permissions were incorrect. Check the bits and return a more helpful
// error message.
//
// NOTE: The error message is checked because error types are lost over
// rpc calls.
if strings.Contains(err.Error(), syscall.EACCES.Error()) {
if permsErr := checkBinaryPermissions(conf); permsErr != nil {
return fmt.Errorf("%v: %v", err, permsErr)
}
}
return err
}
s.child = true
s.Pid = cmd.Process.Pid
@@ -1169,3 +1195,31 @@ func deviceFileForPlatform(name string) (*os.File, error) {
}
return f, nil
}
// checkBinaryPermissions verifies that the required binary bits are set on
// the runsc executable.
func checkBinaryPermissions(conf *boot.Config) error {
// All platforms need the other exe bit
neededBits := os.FileMode(0001)
if conf.Platform == platforms.Ptrace {
// Ptrace needs the other read bit
neededBits |= os.FileMode(0004)
}
exePath, err := os.Executable()
if err != nil {
return fmt.Errorf("getting exe path: %v", err)
}
// Check the permissions of the runsc binary and print an error if it
// doesn't match expectations.
info, err := os.Stat(exePath)
if err != nil {
return fmt.Errorf("stat file: %v", err)
}
if info.Mode().Perm()&neededBits != neededBits {
return fmt.Errorf(specutils.FaqErrorMsg("runsc-perms", fmt.Sprintf("%s does not have the correct permissions", exePath)))
}
return nil
}
+5
View File
@@ -528,3 +528,8 @@ func EnvVar(env []string, name string) (string, bool) {
}
return "", false
}
// FaqErrorMsg returns an error message pointing to the FAQ.
func FaqErrorMsg(anchor, msg string) string {
return fmt.Sprintf("%s; see https://gvisor.dev/faq#%s for more details", msg, anchor)
}