bluez5: guard against transports without sco_io

If backend releases transport early and sco_io becomes NULL, don't
access it.

Also guard against calloc failing in sco_io creation.
This commit is contained in:
Pauli Virtanen 2021-03-20 12:18:13 +02:00 committed by Wim Taymans
parent 79e098bdf2
commit 0385d0a07e
4 changed files with 21 additions and 6 deletions

View file

@ -1575,14 +1575,17 @@ static int spa_bt_transport_stop_release_timer(struct spa_bt_transport *transpor
return 0; return 0;
} }
void spa_bt_transport_ensure_sco_io(struct spa_bt_transport *t, struct spa_loop *data_loop) int spa_bt_transport_ensure_sco_io(struct spa_bt_transport *t, struct spa_loop *data_loop)
{ {
if (t->sco_io == NULL) { if (t->sco_io == NULL) {
t->sco_io = spa_bt_sco_io_create(data_loop, t->sco_io = spa_bt_sco_io_create(data_loop,
t->fd, t->fd,
t->read_mtu, t->read_mtu,
t->write_mtu); t->write_mtu);
if (t->sco_io == NULL)
return -ENOMEM;
} }
return 0;
} }
int64_t spa_bt_transport_get_delay_nsec(struct spa_bt_transport *t) int64_t spa_bt_transport_get_delay_nsec(struct spa_bt_transport *t)

View file

@ -518,7 +518,7 @@ int64_t spa_bt_transport_get_delay_nsec(struct spa_bt_transport *t);
int spa_bt_transport_acquire(struct spa_bt_transport *t, bool optional); int spa_bt_transport_acquire(struct spa_bt_transport *t, bool optional);
int spa_bt_transport_release(struct spa_bt_transport *t); int spa_bt_transport_release(struct spa_bt_transport *t);
void spa_bt_transport_ensure_sco_io(struct spa_bt_transport *t, struct spa_loop *data_loop); int spa_bt_transport_ensure_sco_io(struct spa_bt_transport *t, struct spa_loop *data_loop);
#define spa_bt_transport_emit(t,m,v,...) spa_hook_list_call(&(t)->listener_list, \ #define spa_bt_transport_emit(t,m,v,...) spa_hook_list_call(&(t)->listener_list, \
struct spa_bt_transport_events, \ struct spa_bt_transport_events, \

View file

@ -332,7 +332,7 @@ static void flush_data(struct impl *this)
uint32_t min_in_size; uint32_t min_in_size;
uint8_t *packet; uint8_t *packet;
if (this->transport == NULL) if (this->transport == NULL || this->transport->sco_io == NULL)
return; return;
/* get buffer */ /* get buffer */
@ -560,7 +560,8 @@ static int do_start(struct impl *this)
spa_return_val_if_fail(this->transport->write_mtu <= sizeof(this->port.write_buffer), -EINVAL); spa_return_val_if_fail(this->transport->write_mtu <= sizeof(this->port.write_buffer), -EINVAL);
/* start socket i/o */ /* start socket i/o */
spa_bt_transport_ensure_sco_io(this->transport, this->data_loop); if ((res = spa_bt_transport_ensure_sco_io(this->transport, this->data_loop)) < 0)
goto fail;
/* Add the timeout callback */ /* Add the timeout callback */
this->source.data = this; this->source.data = this;
@ -577,6 +578,12 @@ static int do_start(struct impl *this)
this->started = true; this->started = true;
return 0; return 0;
fail:
free(this->buffer);
this->buffer = NULL;
spa_bt_transport_release(this->transport);
return res;
} }
/* Drop any buffered data remaining in the port */ /* Drop any buffered data remaining in the port */

View file

@ -608,13 +608,18 @@ static int do_start(struct impl *this)
} }
/* Start socket i/o */ /* Start socket i/o */
spa_bt_transport_ensure_sco_io(this->transport, this->data_loop); if ((res = spa_bt_transport_ensure_sco_io(this->transport, this->data_loop)) < 0)
goto fail;
spa_loop_invoke(this->data_loop, do_add_source, 0, NULL, 0, true, this); spa_loop_invoke(this->data_loop, do_add_source, 0, NULL, 0, true, this);
/* Set the started flag */ /* Set the started flag */
this->started = true; this->started = true;
return 0; return 0;
fail:
spa_bt_transport_release(this->transport);
return res;
} }
static int do_remove_source(struct spa_loop *loop, static int do_remove_source(struct spa_loop *loop,
@ -626,7 +631,7 @@ static int do_remove_source(struct spa_loop *loop,
{ {
struct impl *this = user_data; struct impl *this = user_data;
if (this->transport) if (this->transport && this->transport->sco_io)
spa_bt_sco_io_set_source_cb(this->transport->sco_io, NULL, NULL); spa_bt_sco_io_set_source_cb(this->transport->sco_io, NULL, NULL);
return 0; return 0;