mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add friendlier messages for frequently encountered errors.
Issue #2270 Issue #1765 PiperOrigin-RevId: 305385436
This commit is contained in:
+14
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user