aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmilio Cota <[email protected]>2022-05-22 22:37:50 -0400
committerMITSUNARI Shigeo <[email protected]>2022-06-01 09:47:57 +0900
commit2a265d9d9f713fb4bdbaf33b050a32415537bfb5 (patch)
tree85668ff6f895d530c307c8e5eff7eaa92c2582c3
parent31ff018ed5a98f216e25ea5382b7cc8d9c6ecadb (diff)
downloadxbyak-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.h41
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