Snap for 7298338 from 7034081e0b5c5f66a9972ef974b5047f360b37a2 to sc-d1-release
Change-Id: I19cfefec394577ed46abd6c073b95f19cc0800d2
diff --git a/include/fmq/MessageQueueBase.h b/include/fmq/MessageQueueBase.h
index 2a29937..9bf20e4 100644
--- a/include/fmq/MessageQueueBase.h
+++ b/include/fmq/MessageQueueBase.h
@@ -1069,6 +1069,12 @@
}
auto writePtr = mWritePtr->load(std::memory_order_relaxed);
+ if (writePtr % sizeof(T) != 0) {
+ hardware::details::logError(
+ "The write pointer has become misaligned. Writing to the queue is no longer "
+ "possible.");
+ return false;
+ }
size_t writeOffset = writePtr % mDesc->getSize();
/*
@@ -1154,6 +1160,12 @@
* stores to mReadPtr from a different thread.
*/
auto readPtr = mReadPtr->load(std::memory_order_relaxed);
+ if (writePtr % sizeof(T) != 0 || readPtr % sizeof(T) != 0) {
+ hardware::details::logError(
+ "The write or read pointer has become misaligned. Reading from the queue is no "
+ "longer possible.");
+ return false;
+ }
if (writePtr - readPtr > mDesc->getSize()) {
mReadPtr->store(writePtr, std::memory_order_release);
diff --git a/tests/msgq_test_client.cpp b/tests/msgq_test_client.cpp
index a971f7d..a6f1ccc 100644
--- a/tests/msgq_test_client.cpp
+++ b/tests/msgq_test_client.cpp
@@ -59,7 +59,7 @@
typedef android::hardware::MessageQueue<int32_t, kSynchronizedReadWrite> MessageQueueSync;
typedef android::hardware::MessageQueue<int32_t, kUnsynchronizedWrite> MessageQueueUnsync;
static const std::string kServiceName = "BnTestAidlMsgQ";
-static constexpr size_t kNumElementsInSyncQueue = 1024;
+static constexpr size_t kNumElementsInSyncQueue = (PAGE_SIZE - 16) / sizeof(int32_t);
enum class SetupType {
SINGLE_FD,
@@ -643,6 +643,47 @@
}
/*
+ * Request mService to write a message to the queue followed by a beginRead().
+ * Get a pointer to the memory region for the that first message. Set the write
+ * counter to the last byte in the ring buffer. Request another write from
+ * mService. The write should fail because the write address is misaligned.
+ */
+TYPED_TEST(SynchronizedReadWriteClient, MisalignedWriteCounter) {
+ if (TypeParam::UserFd) {
+ // When using the second FD for the ring buffer, we can't get to the read/write
+ // counters from a pointer to the ring buffer, so no sense in testing.
+ GTEST_SKIP();
+ }
+ const size_t dataLen = 1;
+ ASSERT_LE(dataLen, kNumElementsInSyncQueue);
+ bool ret = this->requestWriteFmqSync(dataLen);
+ ASSERT_TRUE(ret);
+ // begin read and get a MemTransaction object for the first object in the queue
+ typename TypeParam::MQType::MemTransaction tx;
+ ASSERT_TRUE(this->mQueue->beginRead(dataLen, &tx));
+ // get a pointer to the beginning of the ring buffer
+ const auto& region = tx.getFirstRegion();
+ int32_t* firstStart = region.getAddress();
+
+ // because this is the first location in the ring buffer, we can get
+ // access to the read and write pointer stored in the fd. 8 bytes back for the
+ // write counter and 16 bytes back for the read counter
+ uint64_t* writeCntr = (uint64_t*)((uint8_t*)firstStart - 8);
+
+ // set it to point to the very last byte in the ring buffer
+ *(writeCntr) = this->mQueue->getQuantumCount() * this->mQueue->getQuantumSize() - 1;
+ ASSERT_TRUE(*writeCntr % sizeof(int32_t) != 0);
+
+ // this is not actually necessary, but it's the expected the pattern.
+ this->mQueue->commitRead(dataLen);
+
+ // This next write will be misaligned and will overlap outside of the ring buffer.
+ // The write should fail.
+ ret = this->requestWriteFmqSync(dataLen);
+ EXPECT_FALSE(ret);
+}
+
+/*
* Request mService to write a small number of messages
* to the FMQ. Read and verify each message using
* beginRead/Commit read APIs.