summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/util/util.c41
-rw-r--r--lib/util/util.h1
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.