fuse: handle bad response errors

FUSE is supposed to receive an error code corresponding to Linux errors, but
since it's running in another process we can't guarantee that. So instead of
propogating a nonsensical error code (that can lead, in some cases, to panics),
warn and convert the failure to EINVAL.

PiperOrigin-RevId: 660274364
This commit is contained in:
Kevin Krakauer
2024-08-07 00:57:57 -07:00
committed by gVisor bot
parent 4748786350
commit b1ade52f24
2 changed files with 13 additions and 4 deletions
+8 -3
View File
@@ -13,7 +13,7 @@
// limitations under the License.
// Package linuxerr contains syscall error codes exported as an error interface
// pointers. This allows for fast comparison and return operations comperable
// pointers. This allows for fast comparison and return operations comparable
// to unix.Errno constants.
package linuxerr
@@ -29,7 +29,7 @@ const maxErrno uint32 = errno.EHWPOISON + 1
// The following errors are semantically identical to Errno of type unix.Errno
// or sycall.Errno. However, since the type are distinct ( these are
// *errors.Error), they are not directly comperable. However, the Errno method
// *errors.Error), they are not directly comparable. However, the Errno method
// returns an Errno number such that the error can be compared to unix/syscall.Errno
// (e.g. unix.Errno(EPERM.Errno()) == unix.EPERM is true). Converting unix/syscall.Errno
// to the errors should be done via the lookup methods provided.
@@ -355,7 +355,7 @@ func ToUnix(e *errors.Error) unix.Errno {
return unixErr
}
// Equals compars a linuxerr to a given error.
// Equals compares a linuxerr to a given error.
func Equals(e *errors.Error, err error) bool {
var unixErr unix.Errno
if e != noError {
@@ -366,3 +366,8 @@ func Equals(e *errors.Error, err error) bool {
}
return e == err || unixErr == err
}
// IsValid returns whether err is a valid error number.
func IsValid(errno unix.Errno) bool {
return errno < unix.Errno(maxErrno)
}
+5 -1
View File
@@ -195,7 +195,12 @@ func (r *Response) Error() error {
return nil
}
// If we get a bad error in the response, warn and convert it to EINVAL.
sysErrNo := unix.Errno(-errno)
if !linuxerr.IsValid(sysErrNo) {
log.Warningf("fusefs: invalid response error %d does not correspond to a Linux error", sysErrNo)
sysErrNo = unix.Errno(unix.EINVAL)
}
return error(sysErrNo)
}
@@ -213,7 +218,6 @@ func (r *Response) UnmarshalPayload(m marshal.Marshallable) error {
if haveDataLen < wantDataLen {
log.Warningf("fusefs: Payload too small. Minimum data length required: %d, but got data length %d", wantDataLen, haveDataLen)
return linuxerr.EINVAL
}
// The response data is empty unless there is some payload. And so, doesn't