From 7f6254d1e9be1a2fe71134b40ec9b0d3c2ea1e5d Mon Sep 17 00:00:00 2001 From: Bruno Albuquerque Date: Wed, 8 May 2019 00:47:09 -0700 Subject: [PATCH] Prevent a double softc free. - Keep track if the softc was allocated externally or not. - Only try to deallocate it if it was allocated internally. Do not try to free the softc if we were not the ones allocating it. - Avoid a double free on consecutive calls to device_set_softc. Change-Id: Ibb38e54e9dfd2a80dbb53920970bead626da8ba1 Reviewed-on: https://review.haiku-os.org/c/1441 Reviewed-by: Adrien Destugues --- src/libs/compat/freebsd_network/compat.c | 11 ++++++++++- src/libs/compat/freebsd_network/device.h | 5 +++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libs/compat/freebsd_network/compat.c b/src/libs/compat/freebsd_network/compat.c index 0d5b6385c3..ae3adf783c 100644 --- a/src/libs/compat/freebsd_network/compat.c +++ b/src/libs/compat/freebsd_network/compat.c @@ -268,7 +268,13 @@ device_get_softc(device_t dev) void device_set_softc(device_t dev, void *softc) { + if (!(dev->flags & DEVICE_SOFTC_SET)) { + // Not externally allocated. We own it so we must clean it up. + free(dev->softc); + } + dev->softc = softc; + dev->flags |= DEVICE_SOFTC_SET; } @@ -445,7 +451,10 @@ device_delete_child(device_t parent, device_t child) if (parent->flags & DEVICE_DESC_ALLOCED) free((char *)parent->description); - free(parent->softc); + // Delete softc if we were the ones to allocate it. + if (!(parent->flags & DEVICE_SOFTC_SET)) + free(parent->softc); + free(parent); return 0; } diff --git a/src/libs/compat/freebsd_network/device.h b/src/libs/compat/freebsd_network/device.h index 706144abf8..fbf04ec347 100644 --- a/src/libs/compat/freebsd_network/device.h +++ b/src/libs/compat/freebsd_network/device.h @@ -35,11 +35,12 @@ struct root_device_softc { }; enum { - DEVICE_OPEN = 1 << 0, + DEVICE_OPEN = 1 << 0, DEVICE_CLOSED = 1 << 1, DEVICE_NON_BLOCK = 1 << 2, DEVICE_DESC_ALLOCED = 1 << 3, - DEVICE_ATTACHED = 1 << 4 + DEVICE_ATTACHED = 1 << 4, + DEVICE_SOFTC_SET = 1 << 5 // Set through device_set_softc(). };