summaryrefslogtreecommitdiff
path: root/src/journal/mmap-cache.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2013-12-28 19:33:23 -0500
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2014-01-11 10:07:22 -0500
commitae97089d49d1795a35a443b7b830ee666028e733 (patch)
tree528eab7122f5a7b4bb0cf1ad220164b3c0438323 /src/journal/mmap-cache.c
parent47917e4a4a8f1ee00bb7de3e83f7bfd849abf337 (diff)
journal: fix access to munmapped memory in sd_journal_enumerate_unique
sd_j_e_u needs to keep a reference to an object while comparing it with possibly duplicate objects in other files. Because the size of mmap cache is limited, with enough files and object to compare to, at some point the object being compared would be munmapped, resulting in a segmentation fault. Fix this issue by turning keep_always into a reference count that can be increased and decreased. Other callers which set keep_always=true are unmodified: their references are never released but are ignored when the whole file is closed, which happens at some point. keep_always is increased in sd_j_e_u and later on released.
Diffstat (limited to 'src/journal/mmap-cache.c')
-rw-r--r--src/journal/mmap-cache.c57
1 files changed, 46 insertions, 11 deletions
diff --git a/src/journal/mmap-cache.c b/src/journal/mmap-cache.c
index 117dc2f3a5..7dbbb5ef38 100644
--- a/src/journal/mmap-cache.c
+++ b/src/journal/mmap-cache.c
@@ -38,7 +38,7 @@ typedef struct FileDescriptor FileDescriptor;
struct Window {
MMapCache *cache;
- bool keep_always;
+ unsigned keep_always;
bool in_unused;
int prot;
@@ -185,7 +185,7 @@ static void context_detach_window(Context *c) {
c->window = NULL;
LIST_REMOVE(by_window, w->contexts, c);
- if (!w->contexts && !w->keep_always) {
+ if (!w->contexts && w->keep_always == 0) {
/* Not used anymore? */
LIST_PREPEND(unused, c->cache->unused, w);
if (!c->cache->last_unused)
@@ -360,7 +360,6 @@ static int try_context(
assert(m->n_ref > 0);
assert(fd >= 0);
assert(size > 0);
- assert(ret);
c = hashmap_get(m->contexts, UINT_TO_PTR(context+1));
if (!c)
@@ -378,9 +377,10 @@ static int try_context(
return 0;
}
- c->window->keep_always = c->window->keep_always || keep_always;
+ c->window->keep_always += keep_always;
- *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
+ if (ret)
+ *ret = (uint8_t*) c->window->ptr + (offset - c->window->offset);
return 1;
}
@@ -402,7 +402,6 @@ static int find_mmap(
assert(m->n_ref > 0);
assert(fd >= 0);
assert(size > 0);
- assert(ret);
f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
if (!f)
@@ -422,9 +421,10 @@ static int find_mmap(
return -ENOMEM;
context_attach_window(c, w);
- w->keep_always = w->keep_always || keep_always;
+ w->keep_always += keep_always;
- *ret = (uint8_t*) w->ptr + (offset - w->offset);
+ if (ret)
+ *ret = (uint8_t*) w->ptr + (offset - w->offset);
return 1;
}
@@ -450,7 +450,6 @@ static int add_mmap(
assert(m->n_ref > 0);
assert(fd >= 0);
assert(size > 0);
- assert(ret);
woffset = offset & ~((uint64_t) page_size() - 1ULL);
wsize = size + (offset - woffset);
@@ -520,7 +519,8 @@ static int add_mmap(
c->window = w;
LIST_PREPEND(by_window, w->contexts, c);
- *ret = (uint8_t*) w->ptr + (offset - w->offset);
+ if (ret)
+ *ret = (uint8_t*) w->ptr + (offset - w->offset);
return 1;
}
@@ -541,7 +541,6 @@ int mmap_cache_get(
assert(m->n_ref > 0);
assert(fd >= 0);
assert(size > 0);
- assert(ret);
/* Check whether the current context is the right one already */
r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
@@ -563,6 +562,42 @@ int mmap_cache_get(
return add_mmap(m, fd, prot, context, keep_always, offset, size, st, ret);
}
+int mmap_cache_release(
+ MMapCache *m,
+ int fd,
+ int prot,
+ unsigned context,
+ uint64_t offset,
+ size_t size) {
+
+ FileDescriptor *f;
+ Window *w;
+
+ assert(m);
+ assert(m->n_ref > 0);
+ assert(fd >= 0);
+ assert(size > 0);
+
+ f = hashmap_get(m->fds, INT_TO_PTR(fd + 1));
+ if (!f)
+ return -EBADF;
+
+ assert(f->fd == fd);
+
+ LIST_FOREACH(by_fd, w, f->windows)
+ if (window_matches(w, fd, prot, offset, size))
+ break;
+
+ if (!w)
+ return -ENOENT;
+
+ if (w->keep_always == 0)
+ return -ENOLCK;
+
+ w->keep_always -= 1;
+ return 0;
+}
+
void mmap_cache_close_fd(MMapCache *m, int fd) {
FileDescriptor *f;