This is an automated email from the ASF dual-hosted git repository.
pengzheng pushed a commit to branch
hotfix/595-use-after-free-caused-by-cancelled-tracker
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to
refs/heads/hotfix/595-use-after-free-caused-by-cancelled-tracker by this push:
new 7c65bfce [#595] fix use-after-free caused by cancelled service tracker.
7c65bfce is described below
commit 7c65bfce2792d3ec03d980ec97ef0527200d4a50
Author: PengZheng <[email protected]>
AuthorDate: Wed Jul 26 10:36:50 2023 +0800
[#595] fix use-after-free caused by cancelled service tracker.
---
.../src/discovery_zeroconf_watcher.c | 3 +-
.../framework/include_deprecated/service_tracker.h | 9 +++++
libs/framework/src/bundle_context.c | 27 ++++++-------
libs/framework/src/service_tracker.c | 45 +++++++++++++++-------
4 files changed, 52 insertions(+), 32 deletions(-)
diff --git
a/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_watcher.c
b/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_watcher.c
index 1fcf997c..b62c0301 100644
---
a/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_watcher.c
+++
b/bundles/remote_services/discovery_zeroconf/src/discovery_zeroconf_watcher.c
@@ -153,8 +153,7 @@ celix_status_t
discoveryZeroconfWatcher_create(celix_bundle_context_t *ctx, celi
*watcherOut = watcher;
return CELIX_SUCCESS;
thread_err:
- celix_bundleContext_stopTrackerAsync(ctx, watcher->epListenerTrkId, NULL,
NULL);
- celix_bundleContext_waitForAsyncStopTracker(ctx, watcher->epListenerTrkId);
+ celix_bundleContext_stopTracker(ctx, watcher->epListenerTrkId);
epl_tracker_err:
celix_longHashMap_destroy(watcher->epls);
celix_stringHashMap_destroy(watcher->watchedServices);
diff --git a/libs/framework/include_deprecated/service_tracker.h
b/libs/framework/include_deprecated/service_tracker.h
index a92b290d..d65834f3 100644
--- a/libs/framework/include_deprecated/service_tracker.h
+++ b/libs/framework/include_deprecated/service_tracker.h
@@ -83,6 +83,15 @@ CELIX_FRAMEWORK_DEPRECATED_EXPORT celix_service_tracker_t*
celix_serviceTracker_
);
+/**
+ * Creates a closed service tracker.
+ * It is similar to serviceTracker_create.
+ */
+CELIX_FRAMEWORK_DEPRECATED_EXPORT celix_service_tracker_t*
celix_serviceTracker_createClosedWithOptions(
+ celix_bundle_context_t *ctx,
+ const celix_service_tracking_options_t *opts
+);
+
/**
* Creates and starts (open) a service tracker.
* Note that is different from the serviceTracker_create function, because is
also starts the service tracker
diff --git a/libs/framework/src/bundle_context.c
b/libs/framework/src/bundle_context.c
index 1d78780b..05541e16 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -1235,25 +1235,20 @@ static void
celix_bundleContext_createTrackerOnEventLoop(void *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);
+ celixThreadMutex_unlock(&entry->ctx->mutex);
+ return;
+ }
+ celix_service_tracker_t *tracker =
celix_serviceTracker_createClosedWithOptions(entry->ctx, &entry->opts);
+ if (tracker == NULL) {
+ 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));
} 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));
- }
+ entry->tracker = tracker;
+ }
+ celixThreadMutex_unlock(&entry->ctx->mutex);
+ if (tracker) {
+ serviceTracker_open(tracker);
}
}
diff --git a/libs/framework/src/service_tracker.c
b/libs/framework/src/service_tracker.c
index 750f336b..76e69565 100644
--- a/libs/framework/src/service_tracker.c
+++ b/libs/framework/src/service_tracker.c
@@ -632,28 +632,35 @@ celix_service_tracker_t* celix_serviceTracker_create(
return celix_serviceTracker_createWithOptions(ctx, &opts);
}
-celix_service_tracker_t* celix_serviceTracker_createWithOptions(
- bundle_context_t *ctx,
- const celix_service_tracking_options_t *opts
-) {
- celix_service_tracker_t *tracker = NULL;
+celix_service_tracker_t*
celix_serviceTracker_createClosedWithOptions(celix_bundle_context_t* ctx,
+ const
celix_service_tracking_options_t* opts) {
+ celix_service_tracker_t* tracker = NULL;
const char* serviceName = NULL;
- char *filter = NULL;
+ char* filter = NULL;
assert(ctx != NULL);
assert(opts != NULL);
serviceName = opts->filter.serviceName == NULL ? "*" :
opts->filter.serviceName;
- filter = celix_serviceRegistry_createFilterFor(ctx->framework->registry,
opts->filter.serviceName, opts->filter.versionRange, opts->filter.filter);
- if(filter == NULL) {
- celix_framework_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR,
__FUNCTION__, __BASE_FILE__, __LINE__,
+ filter = celix_serviceRegistry_createFilterFor(
+ ctx->framework->registry, opts->filter.serviceName,
opts->filter.versionRange, opts->filter.filter);
+ if (filter == NULL) {
+ celix_framework_log(ctx->framework->logger,
+ CELIX_LOG_LEVEL_ERROR,
+ __FUNCTION__,
+ __BASE_FILE__,
+ __LINE__,
"Error cannot create filter.");
return NULL;
}
tracker = calloc(1, sizeof(*tracker));
- if(tracker == NULL) {
+ if (tracker == NULL) {
free(filter);
- celix_framework_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR,
__FUNCTION__, __BASE_FILE__, __LINE__,
+ celix_framework_log(ctx->framework->logger,
+ CELIX_LOG_LEVEL_ERROR,
+ __FUNCTION__,
+ __BASE_FILE__,
+ __LINE__,
"No memory for tracker.");
- return NULL;
+ return NULL;
}
tracker->context = ctx;
@@ -661,7 +668,7 @@ celix_service_tracker_t*
celix_serviceTracker_createWithOptions(
tracker->filter = filter;
tracker->state = CELIX_SERVICE_TRACKER_CLOSED;
- //setting callbacks
+ // setting callbacks
tracker->callbackHandle = opts->callbackHandle;
tracker->set = opts->set;
tracker->add = opts->add;
@@ -684,8 +691,18 @@ celix_service_tracker_t*
celix_serviceTracker_createWithOptions(
tracker->currentHighestServiceId = -1;
tracker->listener.handle = tracker;
- tracker->listener.serviceChanged = (void *) serviceTracker_serviceChanged;
+ tracker->listener.serviceChanged = (void*)serviceTracker_serviceChanged;
+ return tracker;
+}
+celix_service_tracker_t* celix_serviceTracker_createWithOptions(
+ bundle_context_t *ctx,
+ const celix_service_tracking_options_t *opts
+) {
+ celix_service_tracker_t *tracker =
celix_serviceTracker_createClosedWithOptions(ctx, opts);
+ if(tracker == NULL) {
+ return NULL;
+ }
serviceTracker_open(tracker);
return tracker;
}