mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
fuse: check write() length correctness
This is consistent with Linux's fs/fuse/dev.c:fuse_do_dev_write(). PiperOrigin-RevId: 660096450
This commit is contained in:
@@ -225,12 +225,18 @@ func (fd *DeviceFD) Write(ctx context.Context, src usermem.IOSequence, opts vfs.
|
||||
return 0, linuxerr.EPERM
|
||||
}
|
||||
|
||||
var hdr linux.FUSEHeaderOut
|
||||
if src.NumBytes() < int64(hdr.SizeBytes()) {
|
||||
return 0, linuxerr.EINVAL
|
||||
}
|
||||
n, err := src.CopyIn(ctx, fd.writeBuf[:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var hdr linux.FUSEHeaderOut
|
||||
hdr.UnmarshalBytes(fd.writeBuf[:])
|
||||
if src.NumBytes() != int64(hdr.Len) {
|
||||
return 0, linuxerr.EINVAL
|
||||
}
|
||||
|
||||
fut, ok := fd.completions[hdr.Unique]
|
||||
if !ok {
|
||||
|
||||
+15
-13
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/fuse.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -32,10 +33,13 @@
|
||||
#include "test/util/file_descriptor.h"
|
||||
#include "test/util/fs_util.h"
|
||||
#include "test/util/linux_capability_util.h"
|
||||
#include "test/util/mount_util.h"
|
||||
#include "test/util/posix_error.h"
|
||||
#include "test/util/temp_path.h"
|
||||
#include "test/util/test_util.h"
|
||||
|
||||
using ::testing::Ge;
|
||||
|
||||
namespace gvisor {
|
||||
namespace testing {
|
||||
|
||||
@@ -49,21 +53,19 @@ TEST(FuseTest, RejectBadInit) {
|
||||
auto mount_point = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
auto mount_opts =
|
||||
absl::StrFormat("fd=%d,user_id=0,group_id=0,rootmode=40000", fd.get());
|
||||
auto mount = ASSERT_NO_ERRNO_AND_VALUE(
|
||||
Mount("fuse", mount_point.path(), "fuse", MS_NODEV | MS_NOSUID,
|
||||
mount_opts, 0 /* umountflags */));
|
||||
|
||||
EXPECT_THAT(mount("fuse", mount_point.path().c_str(), "fuse",
|
||||
MS_NODEV | MS_NOSUID, mount_opts.c_str()),
|
||||
SyscallSucceeds());
|
||||
mount_point.release();
|
||||
// Read the init request so that we have the correct unique ID.
|
||||
alignas(fuse_in_header) char req_buf[FUSE_MIN_READ_BUFFER];
|
||||
ASSERT_THAT(read(fd.get(), req_buf, sizeof(req_buf)),
|
||||
SyscallSucceedsWithValue(Ge(sizeof(fuse_in_header))));
|
||||
|
||||
struct response {
|
||||
uint32_t len;
|
||||
int32_t err;
|
||||
uint64_t uid;
|
||||
} resp;
|
||||
// min value for length is 24 + sizeof(response)
|
||||
resp.len = 24 + sizeof(resp) - 1;
|
||||
resp.err = 0;
|
||||
resp.uid = 2;
|
||||
fuse_out_header resp;
|
||||
resp.len = sizeof(resp) - 1;
|
||||
resp.error = 0;
|
||||
resp.unique = reinterpret_cast<fuse_in_header*>(req_buf)->unique;
|
||||
|
||||
ASSERT_THAT(write(fd.get(), reinterpret_cast<char*>(&resp), sizeof(resp)),
|
||||
SyscallFailsWithErrno(EINVAL));
|
||||
|
||||
Reference in New Issue
Block a user