From: "Pratyush Yadav (Google)" <[email protected]>

Once a memfd is preserved, certain operations are not allowed to
succeed since they might make the state of the memfd inconsistent with
the serialized state. Among these operations are truncating or growing
the memfd. Writes and reads to already existing memfd should succeed.

Add a test that makes sure a preserved memfd does not allow growing or
shrinking, but does allow reads and writes to existing memory to go
thorough.

Signed-off-by: Pratyush Yadav <[email protected]>
Signed-off-by: Pratyush Yadav (Google) <[email protected]>
---
 .../testing/selftests/liveupdate/luo_memfd.c  | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/tools/testing/selftests/liveupdate/luo_memfd.c 
b/tools/testing/selftests/liveupdate/luo_memfd.c
index 56106cd09978..75f88101e7b5 100644
--- a/tools/testing/selftests/liveupdate/luo_memfd.c
+++ b/tools/testing/selftests/liveupdate/luo_memfd.c
@@ -39,6 +39,10 @@
 #define ZERO_SESSION_NAME "zero_session"
 #define ZERO_MEMFD_TOKEN 1
 
+#define PRESERVED_SESSION_NAME "preserved_session"
+#define PRESERVED_MEMFD_TOKEN 1
+#define PRESERVED_BUFFER_SIZE SZ_1M
+
 #define LIVEUPDATE_DEV "/dev/liveupdate"
 static int luo_fd = -1, stage;
 
@@ -136,6 +140,59 @@ TEST(zero_memfd)
        }
 }
 
+/*
+ * Test that preserved memfd can't grow or shrink, but reads and writes still
+ * work.
+ */
+TEST(preserved_ops)
+{
+       char write_buffer[128] = {'A'};
+       int fd, session;
+       char *buffer;
+       struct liveupdate_session_preserve_fd preserve_arg = { .size = 
sizeof(preserve_arg) };
+
+       if (stage != 1)
+               SKIP(return, "test only expected to run on stage 1");
+
+       buffer = malloc(PRESERVED_BUFFER_SIZE);
+       ASSERT_NE(buffer, NULL);
+
+       session = luo_create_session(luo_fd, PRESERVED_SESSION_NAME);
+       ASSERT_GE(session, 0);
+
+       fd = create_random_memfd("preserved_memfd", buffer, 
PRESERVED_BUFFER_SIZE);
+       ASSERT_GE(fd, 0);
+
+       preserve_arg.fd = fd;
+       preserve_arg.token = PRESERVED_MEMFD_TOKEN;
+       ASSERT_GE(ioctl(session, LIVEUPDATE_SESSION_PRESERVE_FD, 
&preserve_arg), 0);
+
+       /*
+        * Write to the preserved memfd (within existing size). This should
+        * work.
+        */
+       ASSERT_GE(lseek(fd, 0, SEEK_SET), 0);
+       /* Write buffer is smaller than total file size. */
+       ASSERT_EQ(write_size(fd, write_buffer, sizeof(write_buffer)), 0);
+       ASSERT_EQ(verify_fd_content(fd, write_buffer, sizeof(write_buffer)), 0);
+
+       /* Try to grow the file using write(). */
+
+       /* First, seek to one byte behind initial size. */
+       ASSERT_GE(lseek(fd, PRESERVED_BUFFER_SIZE - 1, SEEK_SET), 0);
+
+       /*
+        * Then, write some data that should increase the file size. This should
+        * fail.
+        */
+       ASSERT_LT(write_size(fd, write_buffer, sizeof(write_buffer)), 0);
+       ASSERT_EQ(lseek(fd, 0, SEEK_END), PRESERVED_BUFFER_SIZE);
+
+       /* Try to shrink the file using truncate. This should also fail. */
+       ASSERT_LT(ftruncate(fd, PRESERVED_BUFFER_SIZE / 2), 0);
+       ASSERT_EQ(lseek(fd, 0, SEEK_END), PRESERVED_BUFFER_SIZE);
+}
+
 int main(int argc, char *argv[])
 {
        int session, expected_stage = 0;
-- 
2.53.0.473.g4a7958ca14-goog


Reply via email to