Since
40d1c84bf0 ("BUG/MAJOR: ring: free the ring storage not the ring
itself when using maps"), munmap() call for startup_logs's ring and
file-backed rings fails to work (EINVAL) and causes memory leaks during
process cleanup.
munmap() fails because it is called with the ring's usable area pointer
which is an offset from the underlying original memory block allocated
using mmap(). Indeed, ring_area() helper function was misused because
it didn't explicitly mention that the returned address corresponds to
the usable storage's area, not the allocated one.
To fix the issue, we add an explicit ring_allocated_area() helper to
return the allocated area for the ring, just like we already have
ring_allocated_size() for the allocated size, and we properly use both
the allocated size and allocated area to manipulate them using munmap()
and msync().
No backport needed.
int ring_dispatch_messages(struct ring *ring, void *ctx, size_t *ofs_ptr, size_t *last_ofs_ptr, uint flags,
ssize_t (*msg_handler)(void *ctx, struct ist v1, struct ist v2, size_t ofs, size_t len));
-/* returns the ring storage's area */
+/* returns the ring storage's usable area */
static inline void *ring_area(const struct ring *ring)
{
return ring->storage->area;
}
+/* returns the allocated area for the ring. It covers the whole
+ * area made of both the ring_storage and the usable area.
+ */
+static inline void *ring_allocated_area(const struct ring *ring)
+{
+ return ring->storage;
+}
+
/* returns the number of bytes in the ring */
static inline size_t ring_data(const struct ring *ring)
{
{
#ifdef USE_SHM_OPEN
if (r == shm_startup_logs)
- munmap(ring_area(r), STARTUP_LOG_SIZE);
+ munmap(ring_allocated_area(r), STARTUP_LOG_SIZE);
#endif /* ! USE_SHM_OPEN */
ring_free(r);
}
return;
if (sink->type == SINK_TYPE_BUFFER) {
if (sink->store) {
- size_t size = (ring_size(sink->ctx.ring) + 4095UL) & -4096UL;
- void *area = ring_area(sink->ctx.ring);
+ size_t size = (ring_allocated_size(sink->ctx.ring) + 4095UL) & -4096UL;
+ void *area = ring_allocated_area(sink->ctx.ring);
msync(area, size, MS_SYNC);
munmap(area, size);