Add internal version of mmap that makes the SYS_mmap syscall

Libunwind assumes that `mmap` "goes straight through to a system call stub".
But this might not be true as other runtimes (I'm looking at you UCX)
wrap `mmap` and do AS-unsafe stuff again.
This commit is contained in:
Bert Wesarg
2023-03-23 18:33:25 +01:00
committed by Stephen M. Webb
parent 192863f344
commit 5010beb099
7 changed files with 32 additions and 15 deletions

View File

@@ -217,6 +217,26 @@ do { \
#define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */
/* Provide an internal syscall version of mmap to improve signal safety. */
static ALWAYS_INLINE void *
mi_mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
#ifdef SYS_mmap
#ifdef __syscall // prefer over syscall on *BSD
long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset);
#else
long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset);
#endif
// @todo this is very likely Linux specific
if ((unsigned long int)ret > -4096UL)
return MAP_FAILED;
else
return (void *)ret;
#else
return mmap (addr, len, prot, flags, fd, offset);
#endif
}
/* Provide an internal syscall version of munmap to improve signal safety. */
static ALWAYS_INLINE int
mi_munmap (void *addr, size_t len)
@@ -233,9 +253,8 @@ mi_munmap (void *addr, size_t len)
#endif
#define GET_MEMORY(mem, size) \
do { \
/* Hopefully, mmap() goes straight through to a system call stub... */ \
mem = mmap (NULL, size, PROT_READ | PROT_WRITE, \
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
mem = mi_mmap (NULL, size, PROT_READ | PROT_WRITE, \
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \
if (mem == MAP_FAILED) \
mem = NULL; \
} while (0)

View File

@@ -43,10 +43,10 @@ CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr)
* these pages are allocated, but non-accessible.
*/
/* addr, length, prot, flags, fd, fd_offset */
ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset);
ei->image = mi_mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset);
if (ei->image == MAP_FAILED)
{
Debug(0, "error %d in mmap(): %s\n", errno, strerror(errno));
Debug(0, "error in mmap()\n");
ei->image = NULL;
return NULL;
}

View File

@@ -124,10 +124,10 @@ ucd_file_map (ucd_file_t *ucd_file)
_ucd_file_open (ucd_file);
}
ucd_file->image = mmap(NULL, ucd_file->size, PROT_READ, MAP_PRIVATE, ucd_file->fd, 0);
ucd_file->image = mi_mmap(NULL, ucd_file->size, PROT_READ, MAP_PRIVATE, ucd_file->fd, 0);
if (ucd_file->image == MAP_FAILED)
{
Debug(0, "error %d in mmap(%s): %s\n", errno, ucd_file->filename, strerror(errno));
Debug(0, "error in mmap(%s)\n", ucd_file->filename);
ucd_file->image = NULL;
return NULL;
}

View File

@@ -239,10 +239,9 @@ elf_w (extract_minidebuginfo) (struct elf_image *ei, struct elf_image *mdi)
}
mdi->size = uncompressed_len;
mdi->image = mmap (NULL, uncompressed_len, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
GET_MEMORY (mdi->image, uncompressed_len);
if (mdi->image == MAP_FAILED)
if (!mdi->image)
return 0;
size_t in_pos = 0, out_pos = 0;

View File

@@ -85,7 +85,7 @@ elf_map_image (struct elf_image *ei, const char *path)
}
ei->size = stat.st_size;
ei->image = mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE, fd, 0);
ei->image = mi_mmap (NULL, ei->size, PROT_READ, MAP_PRIVATE, fd, 0);
close (fd);
if (ei->image == MAP_FAILED)
return -1;

View File

@@ -37,7 +37,7 @@ get_mem(size_t sz)
{
void *res;
res = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
res = mi_mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (res == MAP_FAILED)
return (NULL);
return (res);

View File

@@ -77,9 +77,8 @@ maps_init (struct map_iterator *mi, pid_t pid)
{
/* Try to allocate a page-sized buffer. */
mi->buf_size = getpagesize ();
cp = mmap (NULL, mi->buf_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (cp == MAP_FAILED)
GET_MEMORY (cp, mi->buf_size);
if (!cp)
{
close(mi->fd);
mi->fd = -1;