diff options
author | Denis Grigorev <d.grigorev@omprussia.ru> | 2020-06-30 16:47:31 +0300 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2020-07-01 10:49:49 -0700 |
commit | 7a35c12a6cebb56fe321dc1276117a94ec827eec (patch) | |
tree | 8788c2f01653b293dd571fad2a2b43cde017e618 /gobex/gobex-transfer.c | |
parent | 96c140c2c4b606c1461348a5b1725441dd98f084 (diff) | |
download | bluez-7a35c12a6cebb56fe321dc1276117a94ec827eec.tar.gz |
gobex: Fix segfault caused by interrupted transfer
When a obex transfer is interrupted by a peer in the middle, the response
G_OBEX_RSP_FORBIDDEN comes and the transfer is freed in transfer_complete.
However gobex is still ref'ed and gobex->io continues to be writable,
so write_data() and then g_obex_abort() are called. When the abort response
comes, struct obc_transfer is already freed, which leads to the crash.
Backtrace :
__GI___pthread_mutex_lock (mutex=0x65732f74) at pthread_mutex_lock.c:67
0xecc6eeda in dbus_connection_get_object_path_data () from libdbus-1.so.3
0x000457d4 in g_dbus_emit_property_changed_full () at gdbus/object.c:1794
0x00045868 in g_dbus_emit_property_changed () at gdbus/object.c:1832
0x000367f0 in transfer_set_status () at obexd/client/transfer.c:211
0x0003681e in transfer_set_status () at obexd/client/transfer.c:206
xfer_complete () at obexd/client/transfer.c:672
0x00022df6 in transfer_complete () at gobex/gobex-transfer.c:103
0x00022f44 in transfer_abort_response () at gobex/gobex-transfer.c:124
0x00020a0e in handle_response () at gobex/gobex.c:1128
0x00020dde in incoming_data () at gobex/gobex.c:1373
This commit introduces g_obex_drop_tx_queue(), which will be called if
a transfer error detected. After the tx queue is dropped, obex shuts
down gracefully.
Diffstat (limited to 'gobex/gobex-transfer.c')
-rw-r--r-- | gobex/gobex-transfer.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/gobex/gobex-transfer.c b/gobex/gobex-transfer.c index bc9930679..e96e61fbc 100644 --- a/gobex/gobex-transfer.c +++ b/gobex/gobex-transfer.c @@ -100,6 +100,11 @@ static void transfer_complete(struct transfer *transfer, GError *err) g_obex_debug(G_OBEX_DEBUG_TRANSFER, "transfer %u", id); + if (err) { + /* No further tx must be performed */ + g_obex_drop_tx_queue(transfer->obex); + } + transfer->complete_func(transfer->obex, err, transfer->user_data); /* Check if the complete_func removed the transfer */ if (find_transfer(id) == NULL) |