mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
process_vm_{read,write}v returns EFAILT if iov-s describe inaccessible memory
PiperOrigin-RevId: 607482542
This commit is contained in:
@@ -127,7 +127,7 @@ func processVMOp(t *kernel.Task, args arch.SyscallArguments, op processVMOpType)
|
||||
n, err = doProcessVMOpMaybeLocked(t, opArgs)
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
if n == 0 && err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return uintptr(n), nil, nil
|
||||
@@ -172,52 +172,40 @@ func doProcessVMOpMaybeLocked(t *kernel.Task, args processVMOpArgs) (int, error)
|
||||
|
||||
// Number of bytes written.
|
||||
var n int
|
||||
for _, readIovec := range readIovecs {
|
||||
if len(writeIovecs) == 0 {
|
||||
break
|
||||
for len(readIovecs) != 0 && len(writeIovecs) != 0 {
|
||||
readIovec := readIovecs[0]
|
||||
length := readIovec.Length()
|
||||
if length == 0 {
|
||||
readIovecs = readIovecs[1:]
|
||||
continue
|
||||
}
|
||||
if length > maxScratchBufferSize {
|
||||
length = maxScratchBufferSize
|
||||
}
|
||||
buf = buf[0:int(length)]
|
||||
bytes, err := args.readCtx.CopyInBytes(readIovec.Start, buf)
|
||||
if bytes == 0 {
|
||||
return n, err
|
||||
}
|
||||
readIovecs[0].Start += hostarch.Addr(bytes)
|
||||
|
||||
for readIovec.Length() != 0 {
|
||||
length := readIovec.Length()
|
||||
if length > maxScratchBufferSize {
|
||||
length = maxScratchBufferSize
|
||||
start := 0
|
||||
for bytes > start && len(writeIovecs) > 0 {
|
||||
writeLength := int(writeIovecs[0].Length())
|
||||
if writeLength == 0 {
|
||||
writeIovecs = writeIovecs[1:]
|
||||
continue
|
||||
}
|
||||
buf = buf[0:int(length)]
|
||||
bytes, err := args.readCtx.CopyInBytes(readIovec.Start, buf)
|
||||
if linuxerr.Equals(linuxerr.EFAULT, err) {
|
||||
return n, nil
|
||||
if writeLength > (bytes - start) {
|
||||
writeLength = bytes - start
|
||||
}
|
||||
if bytes == 0 && err != nil {
|
||||
out, err := args.writeCtx.CopyOutBytes(writeIovecs[0].Start, buf[start:writeLength+start])
|
||||
n += out
|
||||
start += out
|
||||
if out != writeLength {
|
||||
return n, err
|
||||
}
|
||||
readIovec.Start += hostarch.Addr(bytes)
|
||||
|
||||
start := 0
|
||||
for bytes > start && 0 < len(writeIovecs) {
|
||||
writeLength := int(writeIovecs[0].Length())
|
||||
if writeLength > (bytes - start) {
|
||||
writeLength = bytes - start
|
||||
}
|
||||
out, err := args.writeCtx.CopyOutBytes(writeIovecs[0].Start, buf[start:writeLength+start])
|
||||
n += out
|
||||
start += out
|
||||
if linuxerr.Equals(linuxerr.EFAULT, err) {
|
||||
return n, nil
|
||||
}
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if out != writeLength {
|
||||
return n, nil
|
||||
}
|
||||
writeIovecs[0].Start += hostarch.Addr(out)
|
||||
if !writeIovecs[0].WellFormed() {
|
||||
return n, err
|
||||
}
|
||||
if writeIovecs[0].Length() == 0 {
|
||||
writeIovecs = writeIovecs[1:]
|
||||
}
|
||||
}
|
||||
writeIovecs[0].Start += hostarch.Addr(out)
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
|
||||
@@ -4658,6 +4658,7 @@ cc_binary(
|
||||
gtest,
|
||||
"//test/util:cleanup",
|
||||
"//test/util:logging",
|
||||
"//test/util:memory_util",
|
||||
"//test/util:posix_error",
|
||||
"//test/util:test_main",
|
||||
"//test/util:test_util",
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "absl/strings/str_join.h"
|
||||
#include "test/util/cleanup.h"
|
||||
#include "test/util/logging.h"
|
||||
#include "test/util/memory_util.h"
|
||||
#include "test/util/posix_error.h"
|
||||
#include "test/util/test_util.h"
|
||||
#include "test/util/thread_util.h"
|
||||
@@ -406,6 +407,24 @@ TEST(ProcessVMInvalidTest, PartialReadWrite) {
|
||||
SyscallSucceedsWithValue(iov_content_1.size()));
|
||||
}
|
||||
|
||||
TEST(ProcessVMInvalidTest, AccessInvalidMemoryFailsWithEINVAL) {
|
||||
auto const mapping =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(MmapAnon(kPageSize, PROT_NONE, MAP_PRIVATE));
|
||||
struct iovec iov_none, iov_valid;
|
||||
char buf[128];
|
||||
iov_valid.iov_base = buf;
|
||||
iov_valid.iov_len = sizeof(buf);
|
||||
iov_none.iov_base = mapping.ptr();
|
||||
iov_none.iov_len = mapping.len();
|
||||
|
||||
EXPECT_THAT(
|
||||
RetryEINTR(process_vm_writev)(getpid(), &iov_none, 1, &iov_valid, 1, 0),
|
||||
SyscallFailsWithErrno(EFAULT));
|
||||
EXPECT_THAT(
|
||||
RetryEINTR(process_vm_writev)(getpid(), &iov_valid, 1, &iov_none, 1, 0),
|
||||
SyscallFailsWithErrno(EFAULT));
|
||||
}
|
||||
|
||||
TEST(ProcessVMTest, WriteToZombie) {
|
||||
char* data = {0};
|
||||
pid_t child;
|
||||
|
||||
Reference in New Issue
Block a user