From afa345325647e66dc7add78f7100dc81bd066dbb Mon Sep 17 00:00:00 2001 From: Daichi Hirono Date: Thu, 15 Jun 2017 15:48:07 +0900 Subject: Skip FUSE request from /dev/fuse if unique=0 APCT log shows that we got FUSE request unique=0 and replying to such request causes a EINVAL. The possible reasons of getting unique=0 here are: * /dev/fuse actually submits such requests. In this case, not replying to such request probabbly safe as the kernel cannot wait corresponding response without a unique number. We can observing the kernel code to find out what unique=0 actually means. * Memory corruption happens and unique number are cleared with zero. In this case, if we skip unique=0 request, libappfuse does not reply to the kernel request and APCT result will become timeout . To see which case happens, the CL ScopedLogSeverity to output verbose logs and lets FuseBridgeLoop skip a request from /dev/fuse if unique=0. Bug: 62429763 Test: libappfuse_tests Change-Id: I8c4d532564b690d55573b92260170b0cd68150ab --- libappfuse/FuseBridgeLoop.cc | 9 ++++++++- libappfuse/tests/FuseBridgeLoopTest.cc | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'libappfuse') diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc index 07923071b..5a897a472 100644 --- a/libappfuse/FuseBridgeLoop.cc +++ b/libappfuse/FuseBridgeLoop.cc @@ -173,13 +173,20 @@ class FuseBridgeEntry { } FuseBridgeState ReadFromDevice(FuseBridgeLoopCallback* callback) { + // To observe APCT failures. + base::ScopedLogSeverity log_severity(base::VERBOSE); + LOG(VERBOSE) << "ReadFromDevice"; if (!buffer_.request.Read(device_fd_)) { return FuseBridgeState::kClosing; } const uint32_t opcode = buffer_.request.header.opcode; - LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode; + const uint64_t unique = buffer_.request.header.unique; + LOG(VERBOSE) << "Read a fuse packet, opcode=" << opcode << " unique=" << unique; + if (unique == 0) { + return FuseBridgeState::kWaitToReadEither; + } switch (opcode) { case FUSE_FORGET: // Do not reply to FUSE_FORGET. diff --git a/libappfuse/tests/FuseBridgeLoopTest.cc b/libappfuse/tests/FuseBridgeLoopTest.cc index 51d605136..0a28451bf 100644 --- a/libappfuse/tests/FuseBridgeLoopTest.cc +++ b/libappfuse/tests/FuseBridgeLoopTest.cc @@ -67,6 +67,7 @@ class FuseBridgeLoopTest : public ::testing::Test { memset(&request_, 0, sizeof(FuseRequest)); request_.header.opcode = opcode; request_.header.len = sizeof(fuse_in_header); + request_.header.unique = 1; ASSERT_TRUE(request_.Write(dev_sockets_[0])); memset(&response_, 0, sizeof(FuseResponse)); -- cgit v1.2.3