Apache Celix is a framework for C and C++14 to develop dynamic modular software applications using component and in-process service-oriented programming.
When eliminating GOTOs in discovery_zeroconf, we found that replacing the following celix_bundleContext_stopTrackerAsync plus celix_bundleContext_stopTrackerAsync by celix_bundleContext_stop will caused ASAN error in TEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed4).
The difference between the two procedures is that the latter may cancel a tracker while the former will never try to cancel a in-flight tracker. A closer look at service tracker creation reveals that a cancelled tracker will be created and destroyed even if it is cancelled, which in our case will lead to use-after-free.
static void celix_bundleContext_createTrackerOnEventLoop(void *data) {
celix_bundle_context_service_tracker_entry_t* entry = data;
assert(celix_framework_isCurrentThreadTheEventLoop(entry->ctx->framework));
celixThreadMutex_lock(&entry->ctx->mutex);
bool cancelled = entry->cancelled;
celixThreadMutex_unlock(&entry->ctx->mutex);
if (cancelled) {
fw_log(entry->ctx->framework->logger, CELIX_LOG_LEVEL_DEBUG, "Creating of service tracker was cancelled. trk id = %li, svc name tracked = %s", entry->trackerId, entry->opts.filter.serviceName);
} else {
celix_service_tracker_t *tracker = celix_serviceTracker_createWithOptions(entry->ctx, &entry->opts);
if (tracker != NULL) {
celixThreadMutex_lock(&entry->ctx->mutex);
// double-check is necessary to eliminate first-check-then-do race condition
if(!entry->cancelled) {
entry->tracker = tracker;
}
celixThreadMutex_unlock(&entry->ctx->mutex);
if(entry->tracker == NULL) {
assert(entry->cancelled);
celix_serviceTracker_destroy(tracker);
}
} else {
fw_log(entry->ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot create tracker for bnd %s (%li)", celix_bundle_getSymbolicName(entry->ctx->bundle), celix_bundle_getId(entry->ctx->bundle));
}
}
}
When eliminating GOTOs in
discovery_zeroconf
, we found that replacing the followingcelix_bundleContext_stopTrackerAsync
pluscelix_bundleContext_stopTrackerAsync
bycelix_bundleContext_stop
will caused ASAN error inTEST_F(DiscoveryZeroconfWatcherTestSuite, CreateWatcherFailed4)
.The difference between the two procedures is that the latter may cancel a tracker while the former will never try to cancel a in-flight tracker. A closer look at service tracker creation reveals that a cancelled tracker will be created and destroyed even if it is cancelled, which in our case will lead to use-after-free.