Loading libappfuse/FuseBuffer.cc +37 −28 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <algorithm> #include <type_traits> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/macros.h> Loading @@ -34,57 +35,65 @@ static_assert( "FuseBuffer must be standard layout union."); template <typename T> bool FuseMessage<T>::CheckPacketSize(size_t size, const char* name) const { bool FuseMessage<T>::CheckHeaderLength(const char* name) const { const auto& header = static_cast<const T*>(this)->header; if (size >= sizeof(header) && size <= sizeof(T)) { if (header.len >= sizeof(header) && header.len <= sizeof(T)) { return true; } else { LOG(ERROR) << name << " is invalid=" << size; LOG(ERROR) << "Invalid header length is found in " << name << ": " << header.len; return false; } } template <typename T> bool FuseMessage<T>::CheckResult(int result, const char* operation_name) const { if (result == 0) { // Expected close of other endpoints. bool FuseMessage<T>::Read(int fd) { char* const buf = reinterpret_cast<char*>(this); const ssize_t result = TEMP_FAILURE_RETRY(::read(fd, buf, sizeof(T))); if (result < 0) { PLOG(ERROR) << "Failed to read a FUSE message"; return false; } if (result < 0) { PLOG(ERROR) << "Failed to " << operation_name << " a packet"; const auto& header = static_cast<const T*>(this)->header; if (result < static_cast<ssize_t>(sizeof(header))) { LOG(ERROR) << "Read bytes " << result << " are shorter than header size " << sizeof(header); return false; } return true; if (!CheckHeaderLength("Read")) { return false; } template <typename T> bool FuseMessage<T>::CheckHeaderLength(int result, const char* operation_name) const { const auto& header = static_cast<const T*>(this)->header; if (static_cast<uint32_t>(result) == header.len) { return true; } else { LOG(ERROR) << "Invalid header length: operation_name=" << operation_name << " result=" << result << " header.len=" << header.len; if (static_cast<uint32_t>(result) > header.len) { LOG(ERROR) << "Read bytes " << result << " are longer than header.len " << header.len; return false; } if (!base::ReadFully(fd, buf + result, header.len - result)) { PLOG(ERROR) << "ReadFully failed"; return false; } template <typename T> bool FuseMessage<T>::Read(int fd) { const ssize_t result = TEMP_FAILURE_RETRY(::read(fd, this, sizeof(T))); return CheckResult(result, "read") && CheckPacketSize(result, "read count") && CheckHeaderLength(result, "read"); return true; } template <typename T> bool FuseMessage<T>::Write(int fd) const { if (!CheckHeaderLength("Write")) { return false; } const char* const buf = reinterpret_cast<const char*>(this); const auto& header = static_cast<const T*>(this)->header; if (!CheckPacketSize(header.len, "header.len")) { if (!base::WriteFully(fd, buf, header.len)) { PLOG(ERROR) << "WriteFully failed"; return false; } const ssize_t result = TEMP_FAILURE_RETRY(::write(fd, this, header.len)); return CheckResult(result, "write") && CheckHeaderLength(result, "write"); return true; } template class FuseMessage<FuseRequest>; Loading libappfuse/include/libappfuse/FuseBuffer.h +1 −3 Original line number Diff line number Diff line Loading @@ -34,9 +34,7 @@ class FuseMessage { bool Read(int fd); bool Write(int fd) const; private: bool CheckPacketSize(size_t size, const char* name) const; bool CheckResult(int result, const char* operation_name) const; bool CheckHeaderLength(int result, const char* operation_name) const; bool CheckHeaderLength(const char* name) const; }; // FuseRequest represents file operation requests from /dev/fuse. It starts Loading libappfuse/tests/FuseBufferTest.cc +26 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <string.h> #include <sys/socket.h> #include <thread> #include <android-base/unique_fd.h> #include <gtest/gtest.h> Loading Loading @@ -110,6 +112,30 @@ TEST(FuseMessageTest, Write_TooShort) { TestWriteInvalidLength(sizeof(fuse_in_header) - 1); } TEST(FuseMessageTest, ShortWriteAndRead) { int raw_fds[2]; ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, raw_fds)); android::base::unique_fd fds[2]; fds[0].reset(raw_fds[0]); fds[1].reset(raw_fds[1]); const int send_buffer_size = 1024; ASSERT_EQ(0, setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &send_buffer_size, sizeof(int))); bool succeed = false; const int sender_fd = fds[0].get(); std::thread thread([sender_fd, &succeed] { FuseRequest request; request.header.len = 1024 * 4; succeed = request.Write(sender_fd); }); thread.detach(); FuseRequest request; ASSERT_TRUE(request.Read(fds[1])); } TEST(FuseResponseTest, Reset) { FuseResponse response; // Write 1 to the first ten bytes. Loading Loading
libappfuse/FuseBuffer.cc +37 −28 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <algorithm> #include <type_traits> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/macros.h> Loading @@ -34,57 +35,65 @@ static_assert( "FuseBuffer must be standard layout union."); template <typename T> bool FuseMessage<T>::CheckPacketSize(size_t size, const char* name) const { bool FuseMessage<T>::CheckHeaderLength(const char* name) const { const auto& header = static_cast<const T*>(this)->header; if (size >= sizeof(header) && size <= sizeof(T)) { if (header.len >= sizeof(header) && header.len <= sizeof(T)) { return true; } else { LOG(ERROR) << name << " is invalid=" << size; LOG(ERROR) << "Invalid header length is found in " << name << ": " << header.len; return false; } } template <typename T> bool FuseMessage<T>::CheckResult(int result, const char* operation_name) const { if (result == 0) { // Expected close of other endpoints. bool FuseMessage<T>::Read(int fd) { char* const buf = reinterpret_cast<char*>(this); const ssize_t result = TEMP_FAILURE_RETRY(::read(fd, buf, sizeof(T))); if (result < 0) { PLOG(ERROR) << "Failed to read a FUSE message"; return false; } if (result < 0) { PLOG(ERROR) << "Failed to " << operation_name << " a packet"; const auto& header = static_cast<const T*>(this)->header; if (result < static_cast<ssize_t>(sizeof(header))) { LOG(ERROR) << "Read bytes " << result << " are shorter than header size " << sizeof(header); return false; } return true; if (!CheckHeaderLength("Read")) { return false; } template <typename T> bool FuseMessage<T>::CheckHeaderLength(int result, const char* operation_name) const { const auto& header = static_cast<const T*>(this)->header; if (static_cast<uint32_t>(result) == header.len) { return true; } else { LOG(ERROR) << "Invalid header length: operation_name=" << operation_name << " result=" << result << " header.len=" << header.len; if (static_cast<uint32_t>(result) > header.len) { LOG(ERROR) << "Read bytes " << result << " are longer than header.len " << header.len; return false; } if (!base::ReadFully(fd, buf + result, header.len - result)) { PLOG(ERROR) << "ReadFully failed"; return false; } template <typename T> bool FuseMessage<T>::Read(int fd) { const ssize_t result = TEMP_FAILURE_RETRY(::read(fd, this, sizeof(T))); return CheckResult(result, "read") && CheckPacketSize(result, "read count") && CheckHeaderLength(result, "read"); return true; } template <typename T> bool FuseMessage<T>::Write(int fd) const { if (!CheckHeaderLength("Write")) { return false; } const char* const buf = reinterpret_cast<const char*>(this); const auto& header = static_cast<const T*>(this)->header; if (!CheckPacketSize(header.len, "header.len")) { if (!base::WriteFully(fd, buf, header.len)) { PLOG(ERROR) << "WriteFully failed"; return false; } const ssize_t result = TEMP_FAILURE_RETRY(::write(fd, this, header.len)); return CheckResult(result, "write") && CheckHeaderLength(result, "write"); return true; } template class FuseMessage<FuseRequest>; Loading
libappfuse/include/libappfuse/FuseBuffer.h +1 −3 Original line number Diff line number Diff line Loading @@ -34,9 +34,7 @@ class FuseMessage { bool Read(int fd); bool Write(int fd) const; private: bool CheckPacketSize(size_t size, const char* name) const; bool CheckResult(int result, const char* operation_name) const; bool CheckHeaderLength(int result, const char* operation_name) const; bool CheckHeaderLength(const char* name) const; }; // FuseRequest represents file operation requests from /dev/fuse. It starts Loading
libappfuse/tests/FuseBufferTest.cc +26 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include <string.h> #include <sys/socket.h> #include <thread> #include <android-base/unique_fd.h> #include <gtest/gtest.h> Loading Loading @@ -110,6 +112,30 @@ TEST(FuseMessageTest, Write_TooShort) { TestWriteInvalidLength(sizeof(fuse_in_header) - 1); } TEST(FuseMessageTest, ShortWriteAndRead) { int raw_fds[2]; ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, raw_fds)); android::base::unique_fd fds[2]; fds[0].reset(raw_fds[0]); fds[1].reset(raw_fds[1]); const int send_buffer_size = 1024; ASSERT_EQ(0, setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &send_buffer_size, sizeof(int))); bool succeed = false; const int sender_fd = fds[0].get(); std::thread thread([sender_fd, &succeed] { FuseRequest request; request.header.len = 1024 * 4; succeed = request.Write(sender_fd); }); thread.detach(); FuseRequest request; ASSERT_TRUE(request.Read(fds[1])); } TEST(FuseResponseTest, Reset) { FuseResponse response; // Write 1 to the first ten bytes. Loading