From 77b758c59f58a05d1c0d45350796951bc778745f Mon Sep 17 00:00:00 2001 From: Keith Mok Date: Fri, 4 Aug 2023 22:17:08 +0000 Subject: File size seal for memory mapped region When using memfd for cross process communication, we always need to seal the file size, otherwise remote process and shrink the size we memory mapped and thus crash the originate process causing a DoS Bug: 294609150 Test: Build Ignore-AOSP-First: security Change-Id: Ibc263c4f78df897e884378e3d984a188ca8772c7 Merged-In: Ibc263c4f78df897e884378e3d984a188ca8772c7 (cherry picked from commit 3d9f1e3b0a135b784b9ffa0e65d6a699c7ed1f8e) --- libs/binder/MemoryHeapBase.cpp | 4 ++-- libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp index 8fe1d2bb3d..34e747ef21 100644 --- a/libs/binder/MemoryHeapBase.cpp +++ b/libs/binder/MemoryHeapBase.cpp @@ -73,8 +73,8 @@ MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) ALOGV("MemoryHeapBase: Attempting to force MemFD"); fd = memfd_create_region(name ? name : "MemoryHeapBase", size); if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return; - const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) | - ((mFlags & MEMFD_ALLOW_SEALING_FLAG) ? 0 : F_SEAL_SEAL); + const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) | F_SEAL_GROW | + F_SEAL_SHRINK | ((mFlags & MEMFD_ALLOW_SEALING_FLAG) ? 0 : F_SEAL_SEAL); if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) { ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error %s", name, SEAL_FLAGS, strerror(errno)); diff --git a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp index 278dd2bf81..140270f5a1 100644 --- a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp +++ b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp @@ -37,7 +37,8 @@ TEST(MemoryHeapBase, MemfdSealed) { ASSERT_NE(mHeap.get(), nullptr); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL); + EXPECT_EQ(ftruncate(fd, 4096), -1); } TEST(MemoryHeapBase, MemfdUnsealed) { @@ -48,7 +49,8 @@ TEST(MemoryHeapBase, MemfdUnsealed) { ASSERT_NE(mHeap.get(), nullptr); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), 0); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_GROW | F_SEAL_SHRINK); + EXPECT_EQ(ftruncate(fd, 4096), -1); } TEST(MemoryHeapBase, MemfdSealedProtected) { @@ -59,7 +61,9 @@ TEST(MemoryHeapBase, MemfdSealedProtected) { ASSERT_NE(mHeap.get(), nullptr); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL | F_SEAL_FUTURE_WRITE); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), + F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL | F_SEAL_FUTURE_WRITE); + EXPECT_EQ(ftruncate(fd, 4096), -1); } TEST(MemoryHeapBase, MemfdUnsealedProtected) { @@ -71,7 +75,8 @@ TEST(MemoryHeapBase, MemfdUnsealedProtected) { ASSERT_NE(mHeap.get(), nullptr); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_FUTURE_WRITE); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_FUTURE_WRITE); + EXPECT_EQ(ftruncate(fd, 4096), -1); } #else -- cgit v1.2.3 From f2c1d9d28083fdcba53f346bba5289e72bc4be49 Mon Sep 17 00:00:00 2001 From: Keith Mok Date: Fri, 4 Aug 2023 22:17:08 +0000 Subject: File size seal for memory mapped region When using memfd for cross process communication, we always need to seal the file size, otherwise remote process and shrink the size we memory mapped and thus crash the originate process causing a DoS Bug: 294609150 Test: Build Ignore-AOSP-First: security Change-Id: Ibc263c4f78df897e884378e3d984a188ca8772c7 Merged-In: Ibc263c4f78df897e884378e3d984a188ca8772c7 (cherry picked from commit 3d9f1e3b0a135b784b9ffa0e65d6a699c7ed1f8e) --- libs/binder/MemoryHeapBase.cpp | 4 ++-- libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp index 8132d46940..0968b89eae 100644 --- a/libs/binder/MemoryHeapBase.cpp +++ b/libs/binder/MemoryHeapBase.cpp @@ -73,8 +73,8 @@ MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) ALOGV("MemoryHeapBase: Attempting to force MemFD"); fd = memfd_create_region(name ? name : "MemoryHeapBase", size); if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return; - const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) | - ((mFlags & MEMFD_ALLOW_SEALING) ? 0 : F_SEAL_SEAL); + const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) | F_SEAL_GROW | + F_SEAL_SHRINK | ((mFlags & MEMFD_ALLOW_SEALING) ? 0 : F_SEAL_SEAL); if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) { ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error %s", name, SEAL_FLAGS, strerror(errno)); diff --git a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp index 21cb70be17..7d19fd4cff 100644 --- a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp +++ b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp @@ -35,7 +35,8 @@ TEST(MemoryHeapBase, MemfdSealed) { "Test mapping"); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL); + EXPECT_EQ(ftruncate(fd, 4096), -1); } TEST(MemoryHeapBase, MemfdUnsealed) { @@ -45,7 +46,8 @@ TEST(MemoryHeapBase, MemfdUnsealed) { "Test mapping"); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), 0); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_GROW | F_SEAL_SHRINK); + EXPECT_EQ(ftruncate(fd, 4096), -1); } TEST(MemoryHeapBase, MemfdSealedProtected) { @@ -55,7 +57,9 @@ TEST(MemoryHeapBase, MemfdSealedProtected) { "Test mapping"); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL | F_SEAL_FUTURE_WRITE); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), + F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL | F_SEAL_FUTURE_WRITE); + EXPECT_EQ(ftruncate(fd, 4096), -1); } TEST(MemoryHeapBase, MemfdUnsealedProtected) { @@ -66,7 +70,8 @@ TEST(MemoryHeapBase, MemfdUnsealedProtected) { "Test mapping"); int fd = mHeap->getHeapID(); EXPECT_NE(fd, -1); - EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_FUTURE_WRITE); + EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_FUTURE_WRITE); + EXPECT_EQ(ftruncate(fd, 4096), -1); } #else -- cgit v1.2.3