summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2024-03-06 09:30:16 -0800
committerXin Li <delphij@google.com>2024-03-06 09:30:16 -0800
commitce399ec4c791b3713d018bb6749b9315cc8e293e (patch)
tree7ed3d04de3bdfcb2e97d2ee956e26681f626f9fe
parentc459e6947807cdb8e7d05b3f89ed44e9693a8bf4 (diff)
parent504a00f7ed39acddfa1dc158a2951a0372ec029c (diff)
downloadlibfmq-ce399ec4c791b3713d018bb6749b9315cc8e293e.tar.gz
Merge Android 14 QPR2 to AOSP main
Bug: 319669529 Merged-In: I697a6f7bfcb6373914c07e8473f9b4cfb2dfb423 Change-Id: I321adbcc6b54ccc45fe54e2c868d94880db12490
-rw-r--r--include/fmq/MessageQueueBase.h7
-rw-r--r--tests/aidl/default/TestAidlMsgQ.cpp9
-rw-r--r--tests/msgq_test_client.cpp56
3 files changed, 39 insertions, 33 deletions
diff --git a/include/fmq/MessageQueueBase.h b/include/fmq/MessageQueueBase.h
index 1b71abf..abb28d7 100644
--- a/include/fmq/MessageQueueBase.h
+++ b/include/fmq/MessageQueueBase.h
@@ -1340,6 +1340,13 @@ void* MessageQueueBase<MQDescriptorType, T, flavor>::mapGrantorDescr(uint32_t gr
void* address = mmap(0, mapLength, PROT_READ | PROT_WRITE, MAP_SHARED, handle->data[fdIndex],
mapOffset);
+ if (address == MAP_FAILED && errno == EPERM && flavor == kUnsynchronizedWrite) {
+ // If the supplied memory is read-only, it would fail with EPERM.
+ // Try again to mmap read-only for the kUnsynchronizedWrite case.
+ // kSynchronizedReadWrite cannot use read-only memory because the
+ // read pointer is stored in the shared memory as well.
+ address = mmap(0, mapLength, PROT_READ, MAP_SHARED, handle->data[fdIndex], mapOffset);
+ }
if (address == MAP_FAILED) {
hardware::details::logError(std::string("mmap failed: ") + std::to_string(errno));
return nullptr;
diff --git a/tests/aidl/default/TestAidlMsgQ.cpp b/tests/aidl/default/TestAidlMsgQ.cpp
index 485e75b..d230993 100644
--- a/tests/aidl/default/TestAidlMsgQ.cpp
+++ b/tests/aidl/default/TestAidlMsgQ.cpp
@@ -60,7 +60,14 @@ ndk::ScopedAStatus TestAidlMsgQ::getFmqUnsyncWrite(
*_aidl_return = false;
} else {
*mqDesc = std::move(mFmqUnsynchronized->dupeDesc());
- *_aidl_return = true;
+ // set write-protection so readers can't mmap and write
+ int res = ashmem_set_prot_region(mqDesc->handle.fds[0].get(), PROT_READ);
+ if (res == -1) {
+ ALOGE("Failed to set write protection: %s", strerror(errno));
+ *_aidl_return = false;
+ } else {
+ *_aidl_return = true;
+ }
}
return ndk::ScopedAStatus::ok();
diff --git a/tests/msgq_test_client.cpp b/tests/msgq_test_client.cpp
index b55c368..8cab77e 100644
--- a/tests/msgq_test_client.cpp
+++ b/tests/msgq_test_client.cpp
@@ -163,7 +163,7 @@ class ClientUnsyncTestBase<AidlMessageQueueUnsync> : public ::testing::Test {
bool result = false;
aidl::android::hardware::common::fmq::MQDescriptor<int32_t, UnsynchronizedWrite> desc;
auto ret = service->getFmqUnsyncWrite(configureFmq, userFd, &desc, &result);
- *queue = new (std::nothrow) AidlMessageQueueUnsync(desc);
+ *queue = new (std::nothrow) AidlMessageQueueUnsync(desc, false);
return result && ret.isOk();
}
@@ -187,7 +187,7 @@ class ClientUnsyncTestBase<AidlMessageQueueUnsync> : public ::testing::Test {
}
AidlMessageQueueUnsync* newQueue() {
if (mQueue->isValid())
- return new (std::nothrow) AidlMessageQueueUnsync(mQueue->dupeDesc());
+ return new (std::nothrow) AidlMessageQueueUnsync(mQueue->dupeDesc(), false);
else
return nullptr;
}
@@ -215,7 +215,7 @@ class ClientUnsyncTestBase<MessageQueueUnsync> : public ::testing::Test {
service->getFmqUnsyncWrite(configureFmq, userFd,
[queue](bool ret, const MQDescriptorUnsync<int32_t>& in) {
ASSERT_TRUE(ret);
- *queue = new (std::nothrow) MessageQueueUnsync(in);
+ *queue = new (std::nothrow) MessageQueueUnsync(in, false);
});
return true;
}
@@ -237,7 +237,7 @@ class ClientUnsyncTestBase<MessageQueueUnsync> : public ::testing::Test {
}
MessageQueueUnsync* newQueue() {
- return new (std::nothrow) MessageQueueUnsync(*mQueue->getDesc());
+ return new (std::nothrow) MessageQueueUnsync(*mQueue->getDesc(), false);
}
sp<ITestMsgQ> mService;
@@ -961,11 +961,8 @@ TYPED_TEST(UnsynchronizedWriteClient, SmallInputReaderTest1) {
TYPED_TEST(UnsynchronizedWriteClient, SmallInputWriterTest1) {
const size_t dataLen = 16;
ASSERT_LE(dataLen, this->mNumMessagesMax);
- int32_t data[dataLen];
- initData(data, dataLen);
- ASSERT_TRUE(this->mQueue->write(data, dataLen));
- bool ret = this->requestReadFmqUnsync(dataLen, this->mService);
- ASSERT_TRUE(ret);
+ ASSERT_TRUE(this->requestWriteFmqUnsync(dataLen, this->mService));
+ ASSERT_TRUE(this->requestReadFmqUnsync(dataLen, this->mService));
}
/*
@@ -991,9 +988,9 @@ TYPED_TEST(UnsynchronizedWriteClient, ReadWhenEmpty) {
TYPED_TEST(UnsynchronizedWriteClient, WriteWhenFull) {
std::vector<int32_t> data(this->mNumMessagesMax);
initData(&data[0], this->mNumMessagesMax);
- ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+ ASSERT_TRUE(this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService));
ASSERT_EQ(0UL, this->mQueue->availableToWrite());
- ASSERT_TRUE(this->mQueue->write(&data[0], 1));
+ ASSERT_TRUE(this->requestWriteFmqUnsync(1, this->mService));
bool ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
ASSERT_FALSE(ret);
}
@@ -1028,23 +1025,20 @@ TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest2) {
/*
* Write until FMQ is full.
- * Verify that the number of messages available to write
- * is equal to this->mNumMessagesMax.
* Verify that another write attempt is successful.
- * Request this->mService to read. Verify that read is unsuccessful.
+ * Request this->mService to read. Verify that read is unsuccessful
+ * because of the write rollover.
* Perform another write and verify that the read is successful
* to check if the reader process can recover from the error condition.
*/
TYPED_TEST(UnsynchronizedWriteClient, LargeInputTest3) {
- std::vector<int32_t> data(this->mNumMessagesMax);
- initData(&data[0], this->mNumMessagesMax);
- ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+ ASSERT_TRUE(this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService));
ASSERT_EQ(0UL, this->mQueue->availableToWrite());
- ASSERT_TRUE(this->mQueue->write(&data[0], 1));
+ ASSERT_TRUE(this->requestWriteFmqUnsync(1, this->mService));
bool ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
ASSERT_FALSE(ret);
- ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
+ ASSERT_TRUE(this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService));
ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
ASSERT_TRUE(ret);
@@ -1080,13 +1074,15 @@ TYPED_TEST(UnsynchronizedWriteClient, MultipleWrite) {
const size_t chunkNum = 5;
const size_t numMessages = chunkSize * chunkNum;
ASSERT_LE(numMessages, this->mNumMessagesMax);
- int32_t data[numMessages];
- initData(data, numMessages);
for (size_t i = 0; i < chunkNum; i++) {
- ASSERT_TRUE(this->mQueue->write(data + i * chunkSize, chunkSize));
+ ASSERT_TRUE(this->requestWriteFmqUnsync(chunkSize, this->mService));
}
- bool ret = this->requestReadFmqUnsync(numMessages, this->mService);
- ASSERT_TRUE(ret);
+ ASSERT_EQ(numMessages, this->mQueue->availableToRead());
+ int32_t readData[numMessages] = {};
+ ASSERT_TRUE(this->mQueue->read(readData, numMessages));
+ // verify that data is filled by the service - the messages will contiain
+ // 'chunkSize' because that's the value we passed to the service each write.
+ ASSERT_TRUE(verifyData(readData, chunkSize));
}
/*
@@ -1097,14 +1093,10 @@ TYPED_TEST(UnsynchronizedWriteClient, MultipleWrite) {
*/
TYPED_TEST(UnsynchronizedWriteClient, ReadWriteWrapAround) {
size_t numMessages = this->mNumMessagesMax / 2;
- std::vector<int32_t> data(this->mNumMessagesMax);
- initData(&data[0], this->mNumMessagesMax);
- ASSERT_TRUE(this->mQueue->write(&data[0], numMessages));
- bool ret = this->requestReadFmqUnsync(numMessages, this->mService);
- ASSERT_TRUE(ret);
- ASSERT_TRUE(this->mQueue->write(&data[0], this->mNumMessagesMax));
- ret = this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService);
- ASSERT_TRUE(ret);
+ ASSERT_TRUE(this->requestWriteFmqUnsync(numMessages, this->mService));
+ ASSERT_TRUE(this->requestReadFmqUnsync(numMessages, this->mService));
+ ASSERT_TRUE(this->requestWriteFmqUnsync(this->mNumMessagesMax, this->mService));
+ ASSERT_TRUE(this->requestReadFmqUnsync(this->mNumMessagesMax, this->mService));
}
/*