Skip to content

Commit fd83d8c

Browse files
committed
memory/patcher: fix mremap hook and add hook for shmdt
This commit fixes a bug that can cause crashes and memory corruption when the mremap hook is called. The problem occurs because of the ellipses (...) in the mremap intercept function. The ellipses cover the optional new_addr argument on Linux. This commit removes the ellipses and adds an explicit 5th argument. This commit also adds a hook for shmdt. The code only works on Linux at the moment as it needs to read /proc/self/maps to determine the size of the shared memory segment. Signed-off-by: Nathan Hjelm <hjelmn@lanl.gov>
1 parent ef95570 commit fd83d8c

File tree

1 file changed

+98
-15
lines changed

1 file changed

+98
-15
lines changed

opal/mca/memory/patcher/memory_patcher_component.c

Lines changed: 98 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -148,27 +148,22 @@ static int intercept_munmap(void *start, size_t length)
148148

149149
#if defined (SYS_mremap)
150150

151-
static void *(*original_mremap) (void *, size_t, size_t, int, ...);
151+
/* on linux this function has an optional extra argument but ... can not be used here because it
152+
* causes issues when intercepting a 4-argument mremap call */
153+
static void *(*original_mremap) (void *, size_t, size_t, int, void *);
152154

153-
static void *intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, ...)
155+
static void *intercept_mremap (void *start, size_t oldlen, size_t newlen, int flags, void *new_address)
154156
{
155157
OPAL_PATCHER_BEGIN;
156-
void *result = 0;
157-
#ifdef MREMAP_FIXED
158-
va_list ap;
159-
#endif
160-
void *new_address = NULL;
158+
void *result = MAP_FAILED;
161159

162-
opal_mem_hooks_release_hook (start, oldlen, false);
163-
164-
#ifdef MREMAP_FIXED
165-
if (flags & MREMAP_FIXED) {
166-
va_start(ap, flags);
167-
new_address = va_arg(ap, void*);
160+
if (MAP_FAILED != start && oldlen > 0) {
161+
opal_mem_hooks_release_hook (start, oldlen, true);
162+
}
168163

169-
va_end(ap);
164+
if (!(flags & MREMAP_FIXED)) {
165+
new_address = NULL;
170166
}
171-
#endif
172167

173168
if (!original_mremap) {
174169
result = (void *)(intptr_t) memory_patcher_syscall (SYS_mremap, start, oldlen, newlen, flags, new_address);
@@ -261,6 +256,87 @@ static int intercept_brk (void *addr)
261256

262257
#endif
263258

259+
#if defined(SYS_shmdt) && defined(__linux__)
260+
261+
#include <stdio.h>
262+
#include <fcntl.h>
263+
#include <sys/shm.h>
264+
265+
static size_t memory_patcher_get_shm_seg_size (const void *shmaddr)
266+
{
267+
unsigned long start_addr, end_addr;
268+
char *ptr, *newline;
269+
char buffer[1024];
270+
size_t seg_size = 0;
271+
int fd;
272+
273+
seg_size = 0;
274+
275+
fd = open ("/proc/self/maps", O_RDONLY);
276+
assert (fd >= 0);
277+
278+
for (size_t read_offset = 0 ; ; ) {
279+
ssize_t nread = read(fd, buffer + read_offset, sizeof(buffer) - 1 - read_offset);
280+
if (nread <= 0) {
281+
if (errno == EINTR) {
282+
continue;
283+
}
284+
285+
break;
286+
} else {
287+
buffer[nread + read_offset] = '\0';
288+
}
289+
290+
ptr = buffer;
291+
while ( (newline = strchr(ptr, '\n')) != NULL ) {
292+
/* 00400000-0040b000 r-xp ... \n */
293+
int ret = sscanf(ptr, "%lx-%lx ", &start_addr, &end_addr);
294+
if (ret != 2) {
295+
continue;
296+
}
297+
298+
if (start_addr == (uintptr_t)shmaddr) {
299+
seg_size = end_addr - start_addr;
300+
goto out_close;
301+
}
302+
303+
newline = strchr(ptr, '\n');
304+
if (newline == NULL) {
305+
break;
306+
}
307+
308+
ptr = newline + 1;
309+
}
310+
311+
read_offset = strlen(ptr);
312+
memmove(buffer, ptr, read_offset);
313+
}
314+
315+
out_close:
316+
close(fd);
317+
return seg_size;
318+
}
319+
320+
static int (*original_shmdt) (const void *);
321+
322+
static int intercept_shmdt (const void *shmaddr)
323+
{
324+
OPAL_PATCHER_BEGIN;
325+
int result;
326+
327+
opal_mem_hooks_release_hook (shmaddr, memory_patcher_get_shm_seg_size (shmaddr), false);
328+
329+
if (original_shmdt) {
330+
result = original_shmdt (shmaddr);
331+
} else {
332+
result = memory_patcher_syscall (SYS_shmdt, shmaddr);
333+
}
334+
335+
OPAL_PATCHER_END;
336+
return result;
337+
}
338+
#endif
339+
264340
static int patcher_register (void)
265341
{
266342
mca_memory_patcher_priority = 80;
@@ -318,6 +394,13 @@ static int patcher_open (void)
318394
return rc;
319395
}
320396

397+
#if defined(SYS_shmdt) && defined(__linux__)
398+
rc = opal_patcher->patch_symbol ("shmdt", (uintptr_t) intercept_shmdt, (uintptr_t *) &original_shmdt);
399+
if (OPAL_SUCCESS != rc) {
400+
return rc;
401+
}
402+
#endif
403+
321404
#if defined (SYS_brk)
322405
rc = opal_patcher->patch_symbol ("brk", (uintptr_t)intercept_brk, (uintptr_t *) &original_brk);
323406
#endif

0 commit comments

Comments
 (0)