mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
bluez5: free rfcomm when device is freed
Avoids use-after-free if device gets freed before the corresponding rfcomm.
This commit is contained in:
parent
0beb6bfc6c
commit
87aa18edb1
3 changed files with 33 additions and 11 deletions
|
|
@ -88,6 +88,7 @@ struct rfcomm {
|
|||
struct spa_source source;
|
||||
struct impl *backend;
|
||||
struct spa_bt_device *device;
|
||||
struct spa_hook device_listener;
|
||||
struct spa_bt_transport *transport;
|
||||
struct spa_hook transport_listener;
|
||||
enum spa_bt_profile profile;
|
||||
|
|
@ -174,8 +175,18 @@ static void rfcomm_free(struct rfcomm *rfcomm)
|
|||
spa_hook_remove(&rfcomm->transport_listener);
|
||||
spa_bt_transport_free(rfcomm->transport);
|
||||
}
|
||||
if (rfcomm->device)
|
||||
if (rfcomm->device) {
|
||||
spa_bt_device_report_battery_level(rfcomm->device, SPA_BT_NO_BATTERY);
|
||||
spa_hook_remove(&rfcomm->device_listener);
|
||||
rfcomm->device = NULL;
|
||||
}
|
||||
if (rfcomm->source.fd >= 0) {
|
||||
if (rfcomm->source.loop)
|
||||
spa_loop_remove_source(rfcomm->source.loop, &rfcomm->source);
|
||||
shutdown(rfcomm->source.fd, SHUT_RDWR);
|
||||
close (rfcomm->source.fd);
|
||||
rfcomm->source.fd = -1;
|
||||
}
|
||||
free(rfcomm);
|
||||
}
|
||||
|
||||
|
|
@ -664,8 +675,6 @@ static void rfcomm_event(struct spa_source *source)
|
|||
|
||||
if (source->rmask & (SPA_IO_HUP | SPA_IO_ERR)) {
|
||||
spa_log_info(backend->log, NAME": lost RFCOMM connection.");
|
||||
if (source->loop)
|
||||
spa_loop_remove_source(source->loop, source);
|
||||
rfcomm_free(rfcomm);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1157,6 +1166,17 @@ static int backend_native_ensure_codec(void *data, struct spa_bt_device *device,
|
|||
#endif
|
||||
}
|
||||
|
||||
static void device_destroy(void *data)
|
||||
{
|
||||
struct rfcomm *rfcomm = data;
|
||||
rfcomm_free(rfcomm);
|
||||
}
|
||||
|
||||
static const struct spa_bt_device_events device_events = {
|
||||
SPA_VERSION_BT_DEVICE_EVENTS,
|
||||
.destroy = device_destroy,
|
||||
};
|
||||
|
||||
static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessage *m, void *userdata)
|
||||
{
|
||||
struct impl *backend = userdata;
|
||||
|
|
@ -1221,6 +1241,10 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
|||
rfcomm->source.mask = SPA_IO_IN;
|
||||
rfcomm->source.rmask = 0;
|
||||
|
||||
spa_bt_device_add_listener(d, &rfcomm->device_listener, &device_events, rfcomm);
|
||||
spa_loop_add_source(backend->main_loop, &rfcomm->source);
|
||||
spa_list_append(&backend->rfcomm_list, &rfcomm->link);
|
||||
|
||||
if (d->settings && (str = spa_dict_lookup(d->settings, "bluez5.msbc-support")))
|
||||
rfcomm->msbc_support_enabled_in_config = strcmp(str, "true") == 0 || atoi(str) == 1;
|
||||
else
|
||||
|
|
@ -1270,9 +1294,6 @@ static DBusHandlerResult profile_new_connection(DBusConnection *conn, DBusMessag
|
|||
goto fail_need_memory;
|
||||
dbus_message_unref(r);
|
||||
|
||||
spa_loop_add_source(backend->main_loop, &rfcomm->source);
|
||||
spa_list_append(&backend->rfcomm_list, &rfcomm->link);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
fail_need_memory:
|
||||
|
|
@ -1326,11 +1347,6 @@ static DBusHandlerResult profile_request_disconnection(DBusConnection *conn, DBu
|
|||
|
||||
spa_list_for_each_safe(rfcomm, rfcomm_tmp, &backend->rfcomm_list, link) {
|
||||
if (rfcomm->device == d && rfcomm->profile == profile) {
|
||||
if (rfcomm->source.loop)
|
||||
spa_loop_remove_source(rfcomm->source.loop, &rfcomm->source);
|
||||
shutdown(rfcomm->source.fd, SHUT_RDWR);
|
||||
close (rfcomm->source.fd);
|
||||
rfcomm->source.fd = -1;
|
||||
rfcomm_free(rfcomm);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -675,6 +675,8 @@ static void device_free(struct spa_bt_device *device)
|
|||
|
||||
spa_log_debug(monitor->log, "%p", device);
|
||||
|
||||
spa_bt_device_emit_destroy(device);
|
||||
|
||||
battery_remove(device);
|
||||
device_stop_timer(device);
|
||||
|
||||
|
|
|
|||
|
|
@ -386,6 +386,9 @@ struct spa_bt_device_events {
|
|||
|
||||
/** Profile configuration changed */
|
||||
void (*profiles_changed) (void *data, uint32_t prev_profiles, uint32_t prev_connected);
|
||||
|
||||
/** Device freed */
|
||||
void (*destroy) (void *data);
|
||||
};
|
||||
|
||||
struct spa_bt_device {
|
||||
|
|
@ -446,6 +449,7 @@ int spa_bt_device_report_battery_level(struct spa_bt_device *device, uint8_t per
|
|||
#define spa_bt_device_emit_connected(d,...) spa_bt_device_emit(d, connected, 0, __VA_ARGS__)
|
||||
#define spa_bt_device_emit_codec_switched(d,...) spa_bt_device_emit(d, codec_switched, 0, __VA_ARGS__)
|
||||
#define spa_bt_device_emit_profiles_changed(d,...) spa_bt_device_emit(d, profiles_changed, 0, __VA_ARGS__)
|
||||
#define spa_bt_device_emit_destroy(d) spa_bt_device_emit(d, destroy, 0)
|
||||
#define spa_bt_device_add_listener(d,listener,events,data) \
|
||||
spa_hook_list_append(&(d)->listener_list, listener, events, data)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue