diff --git a/exec.go b/exec.go index 94346e062..891fabbd8 100644 --- a/exec.go +++ b/exec.go @@ -101,7 +101,7 @@ following will output a list of processes running in the container: if err == nil { os.Exit(status) } - return fmt.Errorf("exec failed: %v", err) + return fmt.Errorf("exec failed: %w", err) }, SkipArgReorder: true, } @@ -212,13 +212,13 @@ func getProcess(context *cli.Context, bundle string) (*specs.Process, error) { if len(u) > 1 { gid, err := strconv.Atoi(u[1]) if err != nil { - return nil, fmt.Errorf("parsing %s as int for gid failed: %v", u[1], err) + return nil, fmt.Errorf("parsing %s as int for gid failed: %w", u[1], err) } p.User.GID = uint32(gid) } uid, err := strconv.Atoi(u[0]) if err != nil { - return nil, fmt.Errorf("parsing %s as int for uid failed: %v", u[0], err) + return nil, fmt.Errorf("parsing %s as int for uid failed: %w", u[0], err) } p.User.UID = uint32(uid) } diff --git a/libcontainer/apparmor/apparmor_linux.go b/libcontainer/apparmor/apparmor_linux.go index 744d4e570..17262913e 100644 --- a/libcontainer/apparmor/apparmor_linux.go +++ b/libcontainer/apparmor/apparmor_linux.go @@ -52,7 +52,7 @@ func setProcAttr(attr, value string) error { // changeOnExec reimplements aa_change_onexec from libapparmor in Go func changeOnExec(name string) error { if err := setProcAttr("exec", "exec "+name); err != nil { - return fmt.Errorf("apparmor failed to apply profile: %s", err) + return fmt.Errorf("apparmor failed to apply profile: %w", err) } return nil } diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go index 92606525b..735721bd1 100644 --- a/libcontainer/cgroups/utils.go +++ b/libcontainer/cgroups/utils.go @@ -376,7 +376,7 @@ func WriteCgroupProc(dir string, pid int) error { file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY) if err != nil { - return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err) + return fmt.Errorf("failed to write %v to %v: %w", pid, CgroupProcesses, err) } defer file.Close() @@ -393,7 +393,7 @@ func WriteCgroupProc(dir string, pid int) error { continue } - return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err) + return fmt.Errorf("failed to write %v to %v: %w", pid, CgroupProcesses, err) } return err } diff --git a/libcontainer/configs/config.go b/libcontainer/configs/config.go index 4281593f0..d61a6bb80 100644 --- a/libcontainer/configs/config.go +++ b/libcontainer/configs/config.go @@ -375,7 +375,7 @@ func (c Command) Run(s *specs.State) error { go func() { err := cmd.Wait() if err != nil { - err = fmt.Errorf("error running hook: %v, stdout: %s, stderr: %s", err, stdout.String(), stderr.String()) + err = fmt.Errorf("error running hook: %w, stdout: %s, stderr: %s", err, stdout.String(), stderr.String()) } errC <- err }() diff --git a/libcontainer/configs/validate/validator.go b/libcontainer/configs/validate/validator.go index b02546002..c2500a630 100644 --- a/libcontainer/configs/validate/validator.go +++ b/libcontainer/configs/validate/validator.go @@ -268,10 +268,10 @@ func isHostNetNS(path string) (bool, error) { var st1, st2 unix.Stat_t if err := unix.Stat(currentProcessNetns, &st1); err != nil { - return false, fmt.Errorf("unable to stat %q: %s", currentProcessNetns, err) + return false, &os.PathError{Op: "stat", Path: currentProcessNetns, Err: err} } if err := unix.Stat(path, &st2); err != nil { - return false, fmt.Errorf("unable to stat %q: %s", path, err) + return false, &os.PathError{Op: "stat", Path: path, Err: err} } return (st1.Dev == st2.Dev) && (st1.Ino == st2.Ino), nil diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 5ebac4df6..594943404 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -478,7 +478,7 @@ func (c *linuxContainer) newParentProcess(p *Process) (parentProcess, error) { parentLogPipe, childLogPipe, err := os.Pipe() if err != nil { - return nil, fmt.Errorf("Unable to create the log pipe: %s", err) + return nil, fmt.Errorf("unable to create log pipe: %w", err) } logFilePair := filePair{parentLogPipe, childLogPipe} @@ -771,7 +771,7 @@ func (c *linuxContainer) checkCriuVersion(minVersion int) error { var err error c.criuVersion, err = criu.GetCriuVersion() if err != nil { - return fmt.Errorf("CRIU version check failed: %s", err) + return fmt.Errorf("CRIU version check failed: %w", err) } return compareCriuVersion(c.criuVersion, minVersion) diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go index 3d9a45dc3..b6920abe1 100644 --- a/libcontainer/factory_linux.go +++ b/libcontainer/factory_linux.go @@ -396,7 +396,7 @@ func (l *LinuxFactory) StartInitialization() (err error) { }() defer func() { if e := recover(); e != nil { - err = fmt.Errorf("panic from initialization: %v, %v", e, string(debug.Stack())) + err = fmt.Errorf("panic from initialization: %w, %v", e, string(debug.Stack())) } }() diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index c456cbe7a..83217b4dc 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -158,7 +158,7 @@ func finalizeNamespace(config *initConfig) error { // to the directory, but the user running runc does not. // This is useful in cases where the cwd is also a volume that's been chowned to the container user. default: - return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err) + return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %w", config.Cwd, err) } } @@ -186,7 +186,7 @@ func finalizeNamespace(config *initConfig) error { // Change working directory AFTER the user has been set up, if we haven't done it yet. if doChdir { if err := unix.Chdir(config.Cwd); err != nil { - return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %v", config.Cwd, err) + return fmt.Errorf("chdir to cwd (%q) set in config.json failed: %w", config.Cwd, err) } } if err := system.ClearKeepCaps(); err != nil { @@ -457,7 +457,7 @@ func setupRoute(config *configs.Config) error { func setupRlimits(limits []configs.Rlimit, pid int) error { for _, rlimit := range limits { if err := system.Prlimit(pid, rlimit.Type, unix.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}); err != nil { - return fmt.Errorf("error setting rlimit type %v: %v", rlimit.Type, err) + return fmt.Errorf("error setting rlimit type %v: %w", rlimit.Type, err) } } return nil diff --git a/libcontainer/integration/utils_test.go b/libcontainer/integration/utils_test.go index 0ffbf179b..9350072cc 100644 --- a/libcontainer/integration/utils_test.go +++ b/libcontainer/integration/utils_test.go @@ -35,7 +35,7 @@ func init() { // Call it to make sure images are downloaded, and to get the paths. out, err := exec.Command(getImages).CombinedOutput() if err != nil { - panic(fmt.Errorf("getImages error %s (output: %s)", err, out)) + panic(fmt.Errorf("getImages error %w (output: %s)", err, out)) } // Extract the value of BUSYBOX_IMAGE. found := regexp.MustCompile(`(?m)^BUSYBOX_IMAGE=(.*)$`).FindSubmatchIndex(out) @@ -145,7 +145,7 @@ func remove(dir string) { func copyBusybox(dest string) error { out, err := exec.Command("sh", "-c", fmt.Sprintf("tar --exclude './dev/*' -C %q -xf %q", dest, busyboxTar)).CombinedOutput() if err != nil { - return fmt.Errorf("untar error %q: %q", err, out) + return fmt.Errorf("untar error %w: %q", err, out) } return nil } diff --git a/libcontainer/intelrdt/intelrdt.go b/libcontainer/intelrdt/intelrdt.go index cd6e7bf75..0c11615be 100644 --- a/libcontainer/intelrdt/intelrdt.go +++ b/libcontainer/intelrdt/intelrdt.go @@ -414,7 +414,7 @@ func writeFile(dir, file, data string) error { return fmt.Errorf("no such directory for %s", file) } if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data+"\n"), 0o600); err != nil { - return fmt.Errorf("failed to write %v: %v", data, err) + return fmt.Errorf("failed to write %v: %w", data, err) } return nil } @@ -521,7 +521,7 @@ func WriteIntelRdtTasks(dir string, pid int) error { // Don't attach any pid if -1 is specified as a pid if pid != -1 { if err := ioutil.WriteFile(filepath.Join(dir, IntelRdtTasks), []byte(strconv.Itoa(pid)), 0o600); err != nil { - return fmt.Errorf("failed to write %v: %v", pid, err) + return fmt.Errorf("failed to write %v: %w", pid, err) } } return nil diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 9065b398a..0882cf3e0 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -208,7 +208,7 @@ func mountCmd(cmd configs.Command) error { command.Env = cmd.Env command.Dir = cmd.Dir if out, err := command.CombinedOutput(); err != nil { - return fmt.Errorf("%#v failed: %s: %v", cmd, string(out), err) + return fmt.Errorf("%#v failed: %s: %w", cmd, string(out), err) } return nil } diff --git a/libcontainer/seccomp/seccomp_linux.go b/libcontainer/seccomp/seccomp_linux.go index b14d0ede3..fbbe82197 100644 --- a/libcontainer/seccomp/seccomp_linux.go +++ b/libcontainer/seccomp/seccomp_linux.go @@ -43,23 +43,23 @@ func InitSeccomp(config *configs.Seccomp) error { filter, err := libseccomp.NewFilter(defaultAction) if err != nil { - return fmt.Errorf("error creating filter: %s", err) + return fmt.Errorf("error creating filter: %w", err) } // Add extra architectures for _, arch := range config.Architectures { scmpArch, err := libseccomp.GetArchFromString(arch) if err != nil { - return fmt.Errorf("error validating Seccomp architecture: %s", err) + return fmt.Errorf("error validating Seccomp architecture: %w", err) } if err := filter.AddArch(scmpArch); err != nil { - return fmt.Errorf("error adding architecture to seccomp filter: %s", err) + return fmt.Errorf("error adding architecture to seccomp filter: %w", err) } } // Unset no new privs bit if err := filter.SetNoNewPrivsBit(false); err != nil { - return fmt.Errorf("error setting no new privileges: %s", err) + return fmt.Errorf("error setting no new privileges: %w", err) } // Add a rule for each syscall @@ -72,7 +72,7 @@ func InitSeccomp(config *configs.Seccomp) error { } } if err := patchbpf.PatchAndLoad(config, filter); err != nil { - return fmt.Errorf("error loading seccomp filter into kernel: %s", err) + return fmt.Errorf("error loading seccomp filter into kernel: %w", err) } return nil } @@ -161,13 +161,13 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error { // Convert the call's action to the libseccomp equivalent callAct, err := getAction(call.Action, call.ErrnoRet) if err != nil { - return fmt.Errorf("action in seccomp profile is invalid: %s", err) + return fmt.Errorf("action in seccomp profile is invalid: %w", err) } // Unconditional match - just add the rule if len(call.Args) == 0 { if err := filter.AddRule(callNum, callAct); err != nil { - return fmt.Errorf("error adding seccomp filter rule for syscall %s: %s", call.Name, err) + return fmt.Errorf("error adding seccomp filter rule for syscall %s: %w", call.Name, err) } } else { // If two or more arguments have the same condition, @@ -178,7 +178,7 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error { for _, cond := range call.Args { newCond, err := getCondition(cond) if err != nil { - return fmt.Errorf("error creating seccomp syscall condition for syscall %s: %s", call.Name, err) + return fmt.Errorf("error creating seccomp syscall condition for syscall %s: %w", call.Name, err) } argCounts[cond.Index] += 1 @@ -201,14 +201,14 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error { condArr := []libseccomp.ScmpCondition{cond} if err := filter.AddRuleConditional(callNum, callAct, condArr); err != nil { - return fmt.Errorf("error adding seccomp rule for syscall %s: %s", call.Name, err) + return fmt.Errorf("error adding seccomp rule for syscall %s: %w", call.Name, err) } } } else { // No conditions share same argument // Use new, proper behavior if err := filter.AddRuleConditional(callNum, callAct, conditions); err != nil { - return fmt.Errorf("error adding seccomp rule for syscall %s: %s", call.Name, err) + return fmt.Errorf("error adding seccomp rule for syscall %s: %w", call.Name, err) } } } diff --git a/libcontainer/specconv/spec_linux.go b/libcontainer/specconv/spec_linux.go index 01d6f2962..cbcb7d140 100644 --- a/libcontainer/specconv/spec_linux.go +++ b/libcontainer/specconv/spec_linux.go @@ -410,13 +410,13 @@ func initSystemdProps(spec *specs.Spec) ([]systemdDbus.Property, error) { } value, err := dbus.ParseVariant(v, dbus.Signature{}) if err != nil { - return nil, fmt.Errorf("Annotation %s=%s value parse error: %v", k, v, err) + return nil, fmt.Errorf("Annotation %s=%s value parse error: %w", k, v, err) } if isSecSuffix(name) { name = strings.TrimSuffix(name, "Sec") + "USec" value, err = convertSecToUSec(value) if err != nil { - return nil, fmt.Errorf("Annotation %s=%s value parse error: %v", k, v, err) + return nil, fmt.Errorf("Annotation %s=%s value parse error: %w", k, v, err) } } sp = append(sp, systemdDbus.Property{Name: name, Value: value}) diff --git a/libcontainer/sync.go b/libcontainer/sync.go index ac88ad22a..793a55683 100644 --- a/libcontainer/sync.go +++ b/libcontainer/sync.go @@ -48,14 +48,14 @@ func readSync(pipe io.Reader, expected syncType) error { if err == io.EOF { return errors.New("parent closed synchronisation channel") } - return fmt.Errorf("failed reading error from parent: %v", err) + return fmt.Errorf("failed reading error from parent: %w", err) } if procSync.Type == procError { var ierr genericError if err := json.NewDecoder(pipe).Decode(&ierr); err != nil { - return fmt.Errorf("failed reading error from parent: %v", err) + return fmt.Errorf("failed reading error from parent: %w", err) } return &ierr diff --git a/libcontainer/user/user.go b/libcontainer/user/user.go index 78695801c..998daab00 100644 --- a/libcontainer/user/user.go +++ b/libcontainer/user/user.go @@ -305,7 +305,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( if userArg == "" { userArg = strconv.Itoa(user.Uid) } - return nil, fmt.Errorf("unable to find user %s: %v", userArg, err) + return nil, fmt.Errorf("unable to find user %s: %w", userArg, err) } var matchedUserName string @@ -321,7 +321,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( if uidErr != nil { // Not numeric. - return nil, fmt.Errorf("unable to find user %s: %v", userArg, ErrNoPasswdEntries) + return nil, fmt.Errorf("unable to find user %s: %w", userArg, ErrNoPasswdEntries) } user.Uid = uidArg @@ -356,7 +356,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( return g.Name == groupArg }) if err != nil && group != nil { - return nil, fmt.Errorf("unable to find groups for spec %v: %v", matchedUserName, err) + return nil, fmt.Errorf("unable to find groups for spec %v: %w", matchedUserName, err) } // Only start modifying user.Gid if it is in explicit form. @@ -370,7 +370,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) ( if gidErr != nil { // Not numeric. - return nil, fmt.Errorf("unable to find group %s: %v", groupArg, ErrNoGroupEntries) + return nil, fmt.Errorf("unable to find group %s: %w", groupArg, ErrNoGroupEntries) } user.Gid = gidArg @@ -411,7 +411,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err return false }) if err != nil { - return nil, fmt.Errorf("Unable to find additional groups %v: %v", additionalGroups, err) + return nil, fmt.Errorf("Unable to find additional groups %v: %w", additionalGroups, err) } } @@ -434,7 +434,8 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err if !found { gid, err := strconv.ParseInt(ag, 10, 64) if err != nil { - return nil, fmt.Errorf("Unable to find group %s", ag) + // Not a numeric ID either. + return nil, fmt.Errorf("Unable to find group %s: %w", ag, ErrNoGroupEntries) } // Ensure gid is inside gid range. if gid < minID || gid > maxID { diff --git a/libcontainer/utils/utils.go b/libcontainer/utils/utils.go index cd78f23e1..a430a2b93 100644 --- a/libcontainer/utils/utils.go +++ b/libcontainer/utils/utils.go @@ -11,7 +11,7 @@ import ( "strings" "unsafe" - "github.com/cyphar/filepath-securejoin" + securejoin "github.com/cyphar/filepath-securejoin" "golang.org/x/sys/unix" ) @@ -120,7 +120,7 @@ func WithProcfd(root, unsafePath string, fn func(procfd string) error) error { unsafePath = stripRoot(root, unsafePath) path, err := securejoin.SecureJoin(root, unsafePath) if err != nil { - return fmt.Errorf("resolving path inside rootfs failed: %v", err) + return fmt.Errorf("resolving path inside rootfs failed: %w", err) } // Open the target path. diff --git a/libcontainer/utils/utils_unix.go b/libcontainer/utils/utils_unix.go index 1576f2d4a..387ae509d 100644 --- a/libcontainer/utils/utils_unix.go +++ b/libcontainer/utils/utils_unix.go @@ -14,7 +14,7 @@ import ( func EnsureProcHandle(fh *os.File) error { var buf unix.Statfs_t if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil { - return fmt.Errorf("ensure %s is on procfs: %v", fh.Name(), err) + return fmt.Errorf("ensure %s is on procfs: %w", fh.Name(), err) } if buf.Type != unix.PROC_SUPER_MAGIC { return fmt.Errorf("%s is not on procfs", fh.Name()) diff --git a/ps.go b/ps.go index ffe00f37c..cbbb670bf 100644 --- a/ps.go +++ b/ps.go @@ -68,7 +68,7 @@ var psCommand = cli.Command{ cmd := exec.Command("ps", psArgs...) output, err := cmd.CombinedOutput() if err != nil { - return fmt.Errorf("%s: %s", err, output) + return fmt.Errorf("%w: %s", err, output) } lines := strings.Split(string(output), "\n") @@ -85,7 +85,7 @@ var psCommand = cli.Command{ fields := strings.Fields(line) p, err := strconv.Atoi(fields[pidIndex]) if err != nil { - return fmt.Errorf("unexpected pid '%s': %s", fields[pidIndex], err) + return fmt.Errorf("unable to parse pid: %w", err) } for _, pid := range pids { diff --git a/tty.go b/tty.go index 8ca193aa8..c4c72b190 100644 --- a/tty.go +++ b/tty.go @@ -136,7 +136,7 @@ func (t *tty) recvtty(process *libcontainer.Process, socket *os.File) (Err error // Set raw mode for the controlling terminal. if err := t.hostConsole.SetRaw(); err != nil { - return fmt.Errorf("failed to set the terminal from the stdin: %v", err) + return fmt.Errorf("failed to set the terminal from the stdin: %w", err) } go handleInterrupt(t.hostConsole) diff --git a/update.go b/update.go index d7e2d4ba4..e678e2204 100644 --- a/update.go +++ b/update.go @@ -205,7 +205,7 @@ other options are ignored. var err error *pair.dest, err = strconv.ParseUint(val, 10, 64) if err != nil { - return fmt.Errorf("invalid value for %s: %s", pair.opt, err) + return fmt.Errorf("invalid value for %s: %w", pair.opt, err) } } } @@ -221,7 +221,7 @@ other options are ignored. var err error *pair.dest, err = strconv.ParseInt(val, 10, 64) if err != nil { - return fmt.Errorf("invalid value for %s: %s", pair.opt, err) + return fmt.Errorf("invalid value for %s: %w", pair.opt, err) } } } @@ -241,7 +241,7 @@ other options are ignored. if val != "-1" { v, err = units.RAMInBytes(val) if err != nil { - return fmt.Errorf("invalid value for %s: %s", pair.opt, err) + return fmt.Errorf("invalid value for %s: %w", pair.opt, err) } } else { v = -1