diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/util/util.c | 41 | ||||
-rw-r--r-- | lib/util/util.h | 1 |
2 files changed, 40 insertions, 2 deletions
diff --git a/lib/util/util.c b/lib/util/util.c index db71def4c4..35ad49b532 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -936,12 +936,24 @@ bool next_token_no_ltrim_talloc(TALLOC_CTX *ctx, return next_token_internal_talloc(ctx, ptr, pp_buff, sep, false); } +struct anonymous_shared_header { + union { + size_t length; + uint8_t pad[16]; + } u; +}; + /* Map a shared memory buffer of at least nelem counters. */ -void *anonymous_shared_allocate(size_t bufsz) +void *anonymous_shared_allocate(size_t orig_bufsz) { + void *ptr; void *buf; size_t pagesz = getpagesize(); size_t pagecnt; + size_t bufsz = orig_bufsz; + struct anonymous_shared_header *hdr; + + bufsz += sizeof(*hdr); /* round up to full pages */ pagecnt = bufsz / pagesz; @@ -950,6 +962,12 @@ void *anonymous_shared_allocate(size_t bufsz) } bufsz = pagesz * pagecnt; + if (orig_bufsz >= bufsz) { + /* integer wrap */ + errno = ENOMEM; + return NULL; + } + #ifdef MAP_ANON /* BSD */ buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, @@ -963,8 +981,27 @@ void *anonymous_shared_allocate(size_t bufsz) return NULL; } - return buf; + hdr = (struct anonymous_shared_header *)buf; + hdr->u.length = bufsz; + + ptr = (void *)(&hdr[1]); + + return ptr; +} + +void anonymous_shared_free(void *ptr) +{ + struct anonymous_shared_header *hdr; + + if (ptr == NULL) { + return; + } + + hdr = (struct anonymous_shared_header *)ptr; + + hdr--; + munmap(hdr, hdr->u.length); } #ifdef DEVELOPER diff --git a/lib/util/util.h b/lib/util/util.h index 04ea20d07d..8f4fd8f70b 100644 --- a/lib/util/util.h +++ b/lib/util/util.h @@ -859,6 +859,7 @@ bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, * Allocate anonymous shared memory of the given size */ void *anonymous_shared_allocate(size_t bufsz); +void anonymous_shared_free(void *ptr); /* run a command as a child process, with a timeout. |