diff options
author | Emilio Cota <[email protected]> | 2022-05-22 22:37:50 -0400 |
---|---|---|
committer | MITSUNARI Shigeo <[email protected]> | 2022-06-01 09:47:57 +0900 |
commit | 2a265d9d9f713fb4bdbaf33b050a32415537bfb5 (patch) | |
tree | 85668ff6f895d530c307c8e5eff7eaa92c2582c3 | |
parent | 31ff018ed5a98f216e25ea5382b7cc8d9c6ecadb (diff) | |
download | xbyak-2a265d9d9f713fb4bdbaf33b050a32415537bfb5.tar.gz xbyak-2a265d9d9f713fb4bdbaf33b050a32415537bfb5.zip |
memfd: keep file descriptor open during allocation lifetime
Otherwise checkpoint/restore cannot work without CAP_SYS_ADMIN,
since closed memfd's cannot be migrated by unprivileged users.
While at it, close the file when before returning from a
ftruncate/mmap failure.
-rw-r--r-- | xbyak/xbyak.h | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index 5e61e3a..a584f2f 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -418,9 +418,18 @@ inline int getMacOsVersion() } // util #endif class MmapAllocator : public Allocator { + struct Allocation { + size_t size; +#if defined(XBYAK_USE_MEMFD) + // fd_ is only used with XBYAK_USE_MEMFD. We keep the file open + // during the lifetime of each allocation in order to support + // checkpoint/restore by unprivileged users. + int fd; +#endif + }; const std::string name_; // only used with XBYAK_USE_MEMFD - typedef XBYAK_STD_UNORDERED_MAP<uintptr_t, size_t> SizeList; - SizeList sizeList_; + typedef XBYAK_STD_UNORDERED_MAP<uintptr_t, Allocation> AllocationList; + AllocationList allocList_; public: explicit MmapAllocator(const std::string& name = "xbyak") : name_(name) {} uint8_t *alloc(size_t size) @@ -443,25 +452,35 @@ public: fd = memfd_create(name_.c_str(), MFD_CLOEXEC); if (fd != -1) { mode = MAP_SHARED; - if (ftruncate(fd, size) != 0) XBYAK_THROW_RET(ERR_CANT_ALLOC, 0) + if (ftruncate(fd, size) != 0) { + close(fd); + XBYAK_THROW_RET(ERR_CANT_ALLOC, 0) + } } #endif void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, mode, fd, 0); + if (p == MAP_FAILED) { + if (fd != -1) close(fd); + XBYAK_THROW_RET(ERR_CANT_ALLOC, 0) + } + assert(p); + Allocation &alloc = allocList_[(uintptr_t)p]; + alloc.size = size; #if defined(XBYAK_USE_MEMFD) - if (fd != -1) close(fd); + alloc.fd = fd; #endif - if (p == MAP_FAILED) XBYAK_THROW_RET(ERR_CANT_ALLOC, 0) - assert(p); - sizeList_[(uintptr_t)p] = size; return (uint8_t*)p; } void free(uint8_t *p) { if (p == 0) return; - SizeList::iterator i = sizeList_.find((uintptr_t)p); - if (i == sizeList_.end()) XBYAK_THROW(ERR_BAD_PARAMETER) - if (munmap((void*)i->first, i->second) < 0) XBYAK_THROW(ERR_MUNMAP) - sizeList_.erase(i); + AllocationList::iterator i = allocList_.find((uintptr_t)p); + if (i == allocList_.end()) XBYAK_THROW(ERR_BAD_PARAMETER) + if (munmap((void*)i->first, i->second.size) < 0) XBYAK_THROW(ERR_MUNMAP) +#if defined(XBYAK_USE_MEMFD) + if (i->second.fd != -1) close(i->second.fd); +#endif + allocList_.erase(i); } }; #else |