mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[syserror] Add conversions to linuxerr with temporary Equals method.
Add Equals method to compare syserror and unix.Errno errors to linuxerr errors. This will facilitate removal of syserror definitions in a followup, and finding needed conversions from unix.Errno to linuxerr. PiperOrigin-RevId: 380909667
This commit is contained in:
committed by
gVisor bot
parent
01bcd55c3a
commit
e1dc1c78e7
@@ -9,6 +9,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/abi/linux/errno",
|
||||
"//pkg/errors",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package linuxerr
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux/errno"
|
||||
"gvisor.dev/gvisor/pkg/errors"
|
||||
)
|
||||
@@ -325,3 +326,22 @@ func ErrorFromErrno(e errno.Errno) *errors.Error {
|
||||
}
|
||||
panic(fmt.Sprintf("invalid error requested with errno: %d", e))
|
||||
}
|
||||
|
||||
// Equals compars a linuxerr to a given error
|
||||
// TODO(b/34162363): Remove when syserror is removed.
|
||||
func Equals(e *errors.Error, err error) bool {
|
||||
if err == nil {
|
||||
return e == NOERROR || e == nil
|
||||
}
|
||||
if e == nil {
|
||||
return err == NOERROR || err == unix.Errno(0)
|
||||
}
|
||||
|
||||
switch err.(type) {
|
||||
case *errors.Error:
|
||||
return e == err
|
||||
case unix.Errno, error:
|
||||
return unix.Errno(e.Errno()) == err
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ package syserror_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
@@ -243,3 +245,62 @@ func TestSyscallErrnoToErrors(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestEqualsMethod tests that the Equals method correctly compares syerror,
|
||||
// unix.Errno and linuxerr.
|
||||
// TODO (b/34162363): Remove this.
|
||||
func TestEqualsMethod(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
linuxErr []*gErrors.Error
|
||||
err []error
|
||||
equal bool
|
||||
}{
|
||||
{
|
||||
name: "compare nil",
|
||||
linuxErr: []*gErrors.Error{nil, linuxerr.NOERROR},
|
||||
err: []error{nil, linuxerr.NOERROR, unix.Errno(0)},
|
||||
equal: true,
|
||||
},
|
||||
{
|
||||
name: "linuxerr nil error not",
|
||||
linuxErr: []*gErrors.Error{nil, linuxerr.NOERROR},
|
||||
err: []error{unix.Errno(1), linuxerr.EPERM, syserror.EACCES},
|
||||
equal: false,
|
||||
},
|
||||
{
|
||||
name: "linuxerr not nil error nil",
|
||||
linuxErr: []*gErrors.Error{linuxerr.ENOENT},
|
||||
err: []error{nil, unix.Errno(0), linuxerr.NOERROR},
|
||||
equal: false,
|
||||
},
|
||||
{
|
||||
name: "equal errors",
|
||||
linuxErr: []*gErrors.Error{linuxerr.ESRCH},
|
||||
err: []error{linuxerr.ESRCH, syserror.ESRCH, unix.Errno(linuxerr.ESRCH.Errno())},
|
||||
equal: true,
|
||||
},
|
||||
{
|
||||
name: "unequal errors",
|
||||
linuxErr: []*gErrors.Error{linuxerr.ENOENT},
|
||||
err: []error{linuxerr.ESRCH, syserror.ESRCH, unix.Errno(linuxerr.ESRCH.Errno())},
|
||||
equal: false,
|
||||
},
|
||||
{
|
||||
name: "other error",
|
||||
linuxErr: []*gErrors.Error{nil, linuxerr.NOERROR, linuxerr.E2BIG, linuxerr.EINVAL},
|
||||
err: []error{fs.ErrInvalid, io.EOF},
|
||||
equal: false,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
for _, le := range tc.linuxErr {
|
||||
for _, e := range tc.err {
|
||||
if linuxerr.Equals(le, e) != tc.equal {
|
||||
t.Fatalf("Expected %t from Equals method for linuxerr: %s %T and error: %s %T", tc.equal, le, le, e, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ go_library(
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/amutex",
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/log",
|
||||
"//pkg/p9",
|
||||
@@ -110,6 +111,7 @@ go_test(
|
||||
deps = [
|
||||
":fs",
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/sentry/fs/fsutil",
|
||||
"//pkg/sentry/fs/ramfs",
|
||||
"//pkg/sentry/fs/tmpfs",
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/memmap"
|
||||
@@ -410,7 +411,7 @@ func copyAttributesLocked(ctx context.Context, upper *Inode, lower *Inode) error
|
||||
return err
|
||||
}
|
||||
lowerXattr, err := lower.ListXattr(ctx, linux.XATTR_SIZE_MAX)
|
||||
if err != nil && err != syserror.EOPNOTSUPP {
|
||||
if err != nil && !linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/refs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
|
||||
@@ -1439,7 +1440,7 @@ func Rename(ctx context.Context, root *Dirent, oldParent *Dirent, oldName string
|
||||
// replaced is the dirent that is being overwritten by rename.
|
||||
replaced, err := newParent.walk(ctx, root, newName, false /* may unlock */)
|
||||
if err != nil {
|
||||
if err != syserror.ENOENT {
|
||||
if !linuxerr.Equals(linuxerr.ENOENT, err) {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ go_library(
|
||||
visibility = ["//pkg/sentry:internal"],
|
||||
deps = [
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/fd",
|
||||
"//pkg/fdnotifier",
|
||||
"//pkg/log",
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/fdnotifier"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
@@ -158,7 +159,7 @@ func (p *pipeOperations) Write(ctx context.Context, file *fs.File, src usermem.I
|
||||
// isBlockError unwraps os errors and checks if they are caused by EAGAIN or
|
||||
// EWOULDBLOCK. This is so they can be transformed into syserror.ErrWouldBlock.
|
||||
func isBlockError(err error) bool {
|
||||
if err == syserror.EAGAIN || err == syserror.EWOULDBLOCK {
|
||||
if linuxerr.Equals(linuxerr.EAGAIN, err) || linuxerr.Equals(linuxerr.EWOULDBLOCK, err) {
|
||||
return true
|
||||
}
|
||||
if pe, ok := err.(*os.PathError); ok {
|
||||
|
||||
@@ -26,6 +26,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/fd",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/log",
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/p9"
|
||||
"gvisor.dev/gvisor/pkg/sentry/device"
|
||||
@@ -66,7 +67,7 @@ func (i *inodeOperations) Lookup(ctx context.Context, dir *fs.Inode, name string
|
||||
// Get a p9.File for name.
|
||||
qids, newFile, mask, p9attr, err := i.fileState.file.walkGetAttr(ctx, []string{name})
|
||||
if err != nil {
|
||||
if err == syserror.ENOENT {
|
||||
if linuxerr.Equals(linuxerr.ENOENT, err) {
|
||||
if cp.cacheNegativeDirents() {
|
||||
// Return a negative Dirent. It will stay cached until something
|
||||
// is created over it.
|
||||
@@ -298,7 +299,7 @@ func (i *inodeOperations) CreateFifo(ctx context.Context, dir *fs.Inode, name st
|
||||
|
||||
// N.B. FIFOs use major/minor numbers 0.
|
||||
if _, err := i.fileState.file.mknod(ctx, name, mode, 0, 0, p9.UID(owner.UID), p9.GID(owner.GID)); err != nil {
|
||||
if i.session().overrides == nil || err != syserror.EPERM {
|
||||
if i.session().overrides == nil || !linuxerr.Equals(linuxerr.EPERM, err) {
|
||||
return err
|
||||
}
|
||||
// If gofer doesn't support mknod, check if we can create an internal fifo.
|
||||
|
||||
@@ -28,6 +28,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/fd",
|
||||
"//pkg/fdnotifier",
|
||||
"//pkg/iovec",
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/fdnotifier"
|
||||
"gvisor.dev/gvisor/pkg/refs"
|
||||
@@ -213,7 +214,7 @@ func (c *ConnectedEndpoint) Send(ctx context.Context, data [][]byte, controlMess
|
||||
// block (and only for stream sockets).
|
||||
err = syserror.EAGAIN
|
||||
}
|
||||
if n > 0 && err != syserror.EAGAIN {
|
||||
if n > 0 && !linuxerr.Equals(linuxerr.EAGAIN, err) {
|
||||
// The caller may need to block to send more data, but
|
||||
// otherwise there isn't anything that can be done about an
|
||||
// error with a partial write.
|
||||
|
||||
@@ -17,6 +17,7 @@ package host
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/marshal/primitive"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
@@ -191,7 +192,7 @@ func (t *TTYFileOperations) Ioctl(ctx context.Context, _ *fs.File, io usermem.IO
|
||||
if err := t.checkChange(ctx, linux.SIGTTOU); err != nil {
|
||||
// drivers/tty/tty_io.c:tiocspgrp() converts -EIO from
|
||||
// tty_check_change() to -ENOTTY.
|
||||
if err == syserror.EIO {
|
||||
if linuxerr.Equals(linuxerr.EIO, err) {
|
||||
return 0, syserror.ENOTTY
|
||||
}
|
||||
return 0, err
|
||||
|
||||
@@ -19,12 +19,12 @@ import (
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/device"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
|
||||
ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
func nodeType(s *unix.Stat_t) fs.InodeType {
|
||||
@@ -98,7 +98,7 @@ type dirInfo struct {
|
||||
// isBlockError unwraps os errors and checks if they are caused by EAGAIN or
|
||||
// EWOULDBLOCK. This is so they can be transformed into syserror.ErrWouldBlock.
|
||||
func isBlockError(err error) bool {
|
||||
if err == syserror.EAGAIN || err == syserror.EWOULDBLOCK {
|
||||
if linuxerr.Equals(linuxerr.EAGAIN, err) || linuxerr.Equals(linuxerr.EWOULDBLOCK, err) {
|
||||
return true
|
||||
}
|
||||
if pe, ok := err.(*os.PathError); ok {
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
@@ -71,7 +72,7 @@ func overlayLookup(ctx context.Context, parent *overlayEntry, inode *Inode, name
|
||||
// A file could have been created over a whiteout, so we need to
|
||||
// check if something exists in the upper file system first.
|
||||
child, err := parent.upper.Lookup(ctx, name)
|
||||
if err != nil && err != syserror.ENOENT {
|
||||
if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
|
||||
// We encountered an error that an overlay cannot handle,
|
||||
// we must propagate it to the caller.
|
||||
parent.copyMu.RUnlock()
|
||||
@@ -125,7 +126,7 @@ func overlayLookup(ctx context.Context, parent *overlayEntry, inode *Inode, name
|
||||
// Check the lower file system.
|
||||
child, err := parent.lower.Lookup(ctx, name)
|
||||
// Same song and dance as above.
|
||||
if err != nil && err != syserror.ENOENT {
|
||||
if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
|
||||
// Don't leak resources.
|
||||
if upperInode != nil {
|
||||
upperInode.DecRef(ctx)
|
||||
@@ -396,7 +397,7 @@ func overlayRename(ctx context.Context, o *overlayEntry, oldParent *Dirent, rena
|
||||
// newName has been removed out from under us. That's fine;
|
||||
// filesystems where that can happen must handle stale
|
||||
// 'replaced'.
|
||||
if err != nil && err != syserror.ENOENT {
|
||||
if err != nil && !linuxerr.Equals(linuxerr.ENOENT, err) {
|
||||
return err
|
||||
}
|
||||
if err == nil {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/fsutil"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs/ramfs"
|
||||
@@ -191,11 +192,11 @@ func TestLookup(t *testing.T) {
|
||||
} {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
dirent, err := test.dir.Lookup(ctx, test.name)
|
||||
if test.found && (err == syserror.ENOENT || dirent.IsNegative()) {
|
||||
if test.found && (linuxerr.Equals(linuxerr.ENOENT, err) || dirent.IsNegative()) {
|
||||
t.Fatalf("lookup %q expected to find positive dirent, got dirent %v err %v", test.name, dirent, err)
|
||||
}
|
||||
if !test.found {
|
||||
if err != syserror.ENOENT && !dirent.IsNegative() {
|
||||
if !linuxerr.Equals(linuxerr.ENOENT, err) && !dirent.IsNegative() {
|
||||
t.Errorf("lookup %q expected to return ENOENT or negative dirent, got dirent %v err %v", test.name, dirent, err)
|
||||
}
|
||||
// Nothing more to check.
|
||||
|
||||
@@ -30,6 +30,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/log",
|
||||
"//pkg/sentry/fs",
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fs"
|
||||
@@ -34,7 +35,6 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/socket"
|
||||
"gvisor.dev/gvisor/pkg/sentry/socket/unix"
|
||||
"gvisor.dev/gvisor/pkg/sentry/socket/unix/transport"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||
)
|
||||
|
||||
@@ -291,7 +291,7 @@ func (n *netSnmp) ReadSeqFileData(ctx context.Context, h seqfile.SeqHandle) ([]s
|
||||
continue
|
||||
}
|
||||
if err := n.s.Statistics(stat, line.prefix); err != nil {
|
||||
if err == syserror.EOPNOTSUPP {
|
||||
if linuxerr.Equals(linuxerr.EOPNOTSUPP, err) {
|
||||
log.Infof("Failed to retrieve %s of /proc/net/snmp: %v", line.prefix, err)
|
||||
} else {
|
||||
log.Warningf("Failed to retrieve %s of /proc/net/snmp: %v", line.prefix, err)
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
@@ -139,7 +140,7 @@ func Splice(ctx context.Context, dst *File, src *File, opts SpliceOpts) (int64,
|
||||
|
||||
// Attempt to do a WriteTo; this is likely the most efficient.
|
||||
n, err := src.FileOperations.WriteTo(ctx, src, w, opts.Length, opts.Dup)
|
||||
if n == 0 && err == syserror.ENOSYS && !opts.Dup {
|
||||
if n == 0 && linuxerr.Equals(linuxerr.ENOSYS, err) && !opts.Dup {
|
||||
// Attempt as a ReadFrom. If a WriteTo, a ReadFrom may also be
|
||||
// more efficient than a copy if buffers are cached or readily
|
||||
// available. (It's unlikely that they can actually be donated).
|
||||
@@ -151,7 +152,7 @@ func Splice(ctx context.Context, dst *File, src *File, opts SpliceOpts) (int64,
|
||||
// if we block at some point, we could lose data. If the source is
|
||||
// not a pipe then reading is not destructive; if the destination
|
||||
// is a regular file, then it is guaranteed not to block writing.
|
||||
if n == 0 && err == syserror.ENOSYS && !opts.Dup && (!dstPipe || !srcPipe) {
|
||||
if n == 0 && linuxerr.Equals(linuxerr.ENOSYS, err) && !opts.Dup && (!dstPipe || !srcPipe) {
|
||||
// Fallback to an in-kernel copy.
|
||||
n, err = io.Copy(w, &io.LimitedReader{
|
||||
R: r,
|
||||
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/fspath",
|
||||
"//pkg/log",
|
||||
"//pkg/sentry/fs",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user