diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c index 946acb8751..0a75ed79fb 100644 --- a/src/basic/memfd-util.c +++ b/src/basic/memfd-util.c @@ -101,6 +101,22 @@ int memfd_get_sealed(int fd) { return FLAGS_SET(seals, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); } +int memfd_set_sealed_gracefully(int fd) { + int r; + + r = memfd_set_sealed(fd); + if (r != -EPERM) + return r; + + /* Already sealed? Check if required seals are set. */ + r = memfd_get_sealed(fd); + if (r < 0) + return r; + if (r == 0) + return -EPERM; /* Propagate the original error. */ + return 0; +} + int memfd_get_size(int fd, uint64_t *ret) { struct stat stat; diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h index befe41ac43..706d085bed 100644 --- a/src/basic/memfd-util.h +++ b/src/basic/memfd-util.h @@ -19,6 +19,7 @@ static inline int memfd_new_and_seal_string(const char *name, const char *s) { int memfd_set_sealed(int fd); int memfd_get_sealed(int fd); +int memfd_set_sealed_gracefully(int fd); int memfd_get_size(int fd, uint64_t *ret); int memfd_set_size(int fd, uint64_t sz); diff --git a/src/test/test-memfd-util.c b/src/test/test-memfd-util.c index 971a9a8dc0..d7daf78fd4 100644 --- a/src/test/test-memfd-util.c +++ b/src/test/test-memfd-util.c @@ -31,8 +31,11 @@ TEST(memfd_get_sealed) { ASSERT_EQ(size, new_size / 2); ASSERT_OK_ZERO(memfd_get_sealed(fd)); - ASSERT_OK(memfd_set_sealed(fd)); + ASSERT_OK(memfd_set_sealed_gracefully(fd)); ASSERT_OK_POSITIVE(memfd_get_sealed(fd)); + ASSERT_OK(memfd_set_sealed_gracefully(fd)); + ASSERT_OK_POSITIVE(memfd_get_sealed(fd)); + ASSERT_ERROR(memfd_set_sealed(fd), EPERM); } DEFINE_TEST_MAIN(LOG_DEBUG);