From 60c82a9895570677d83d3eb5df22b0a22086cf21 Mon Sep 17 00:00:00 2001 From: xingxing Date: Sat, 12 Feb 2022 09:44:58 +0800 Subject: [PATCH] fix CVE-2021-43400 --- backport-CVE-2021-43400.patch | 336 ++++++++++++++++++++++++++++++++++ bluez.spec | 9 +- 2 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2021-43400.patch diff --git a/backport-CVE-2021-43400.patch b/backport-CVE-2021-43400.patch new file mode 100644 index 0000000..3def24d --- /dev/null +++ b/backport-CVE-2021-43400.patch @@ -0,0 +1,336 @@ +From 838c0dc7641e1c991c0f3027bf94bee4606012f8 Mon Sep 17 00:00:00 2001 +From: Bernie Conrad +Date: Wed, 9 Feb 2022 15:03:19 +0800 +Subject: [PATCH] backport-0003-CVE-2021-43400 + +There is a current use after free possible on a gatt server if a client +disconnects while a WriteValue call is being processed with dbus. + +This patch includes the addition of a pending disconnect callback to handle +cleanup better if a disconnect occurs during a write, an acquire write +or read operation using bt_att_register_disconnect with the cb. + +Conflict:NA +Reference:https://git.kernel.org/pub/scm/bluetooth/bluez.git/commit/?id=b497b5942a8 +--- + src/gatt-database.c | 130 +++++++++++++++++++++++++------------------- + 1 file changed, 74 insertions(+), 56 deletions(-) + +diff --git a/src/gatt-database.c b/src/gatt-database.c +index a6530ba..6dde821 100644 +--- a/src/gatt-database.c ++++ b/src/gatt-database.c +@@ -148,8 +148,9 @@ struct external_desc { + }; + + struct pending_op { +- struct btd_device *device; ++ struct bt_att *att; + unsigned int id; ++ unsigned int disconn_id; + uint16_t offset; + uint8_t link_type; + struct gatt_db_attribute *attrib; +@@ -924,6 +925,25 @@ static struct btd_device *att_get_device(struct bt_att *att) + return btd_adapter_find_device(adapter, &dst, dst_type); + } + ++static void pending_op_free(void *data) ++{ ++ struct pending_op *op = data; ++ ++ if (op->owner_queue) ++ queue_remove(op->owner_queue, op); ++ ++ bt_att_unregister_disconnect(op->att, op->disconn_id); ++ bt_att_unref(op->att); ++ free(op); ++} ++ ++static void pending_disconnect_cb(int err, void *user_data) ++{ ++ struct pending_op *op = user_data; ++ ++ op->owner_queue = NULL; ++} ++ + static struct pending_op *pending_ccc_new(struct bt_att *att, + struct gatt_db_attribute *attrib, + uint16_t value, +@@ -943,21 +963,16 @@ static struct pending_op *pending_ccc_new(struct bt_att *att, + op->data.iov_base = UINT_TO_PTR(value); + op->data.iov_len = sizeof(value); + +- op->device = device; ++ op->att = bt_att_ref(att); + op->attrib = attrib; + op->link_type = link_type; + +- return op; +-} ++ bt_att_register_disconnect(att, ++ pending_disconnect_cb, ++ op, ++ NULL); + +-static void pending_op_free(void *data) +-{ +- struct pending_op *op = data; +- +- if (op->owner_queue) +- queue_remove(op->owner_queue, op); +- +- free(op); ++ return op; + } + + static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib, +@@ -2110,31 +2125,34 @@ done: + gatt_db_attribute_read_result(op->attrib, op->id, ecode, value, len); + } + +-static struct pending_op *pending_read_new(struct btd_device *device, ++static struct pending_op *pending_read_new(struct bt_att *att, + struct queue *owner_queue, + struct gatt_db_attribute *attrib, +- unsigned int id, uint16_t offset, +- uint8_t link_type) ++ unsigned int id, uint16_t offset) + { + struct pending_op *op; + + op = new0(struct pending_op, 1); + + op->owner_queue = owner_queue; +- op->device = device; ++ op->att = bt_att_ref(att); + op->attrib = attrib; + op->id = id; + op->offset = offset; +- op->link_type = link_type; ++ op->link_type = bt_att_get_link_type(att); + queue_push_tail(owner_queue, op); + ++ op->disconn_id = bt_att_register_disconnect(att, pending_disconnect_cb, ++ op, NULL); ++ + return op; + } + + static void append_options(DBusMessageIter *iter, void *user_data) + { + struct pending_op *op = user_data; +- const char *path = device_get_path(op->device); ++ struct btd_device *device = att_get_device(op->att); ++ const char *path = device_get_path(device); + struct bt_gatt_server *server; + const char *link; + uint16_t mtu; +@@ -2161,7 +2179,7 @@ static void append_options(DBusMessageIter *iter, void *user_data) + dict_append_entry(iter, "prepare-authorize", DBUS_TYPE_BOOLEAN, + &op->prep_authorize); + +- server = btd_device_get_gatt_server(op->device); ++ server = btd_device_get_gatt_server(device); + mtu = bt_gatt_server_get_mtu(server); + + dict_append_entry(iter, "mtu", DBUS_TYPE_UINT16, &mtu); +@@ -2184,18 +2202,16 @@ static void read_setup_cb(DBusMessageIter *iter, void *user_data) + dbus_message_iter_close_container(iter, &dict); + } + +-static struct pending_op *send_read(struct btd_device *device, ++static struct pending_op *send_read(struct bt_att *att, + struct gatt_db_attribute *attrib, + GDBusProxy *proxy, + struct queue *owner_queue, + unsigned int id, +- uint16_t offset, +- uint8_t link_type) ++ uint16_t offset) + { + struct pending_op *op; + +- op = pending_read_new(device, owner_queue, attrib, id, offset, +- link_type); ++ op = pending_read_new(att, owner_queue, attrib, id, offset); + + if (g_dbus_proxy_method_call(proxy, "ReadValue", read_setup_cb, + read_reply_cb, op, pending_op_free) == TRUE) +@@ -2278,15 +2294,17 @@ static void write_reply_cb(DBusMessage *message, void *user_data) + } + + done: +- gatt_db_attribute_write_result(op->attrib, op->id, ecode); ++ /* Make sure that only reply if the device is connected */ ++ if (!bt_att_get_fd(op->att)) ++ gatt_db_attribute_write_result(op->attrib, op->id, ecode); + } + +-static struct pending_op *pending_write_new(struct btd_device *device, ++static struct pending_op *pending_write_new(struct bt_att *att, + struct queue *owner_queue, + struct gatt_db_attribute *attrib, + unsigned int id, + const uint8_t *value, size_t len, +- uint16_t offset, uint8_t link_type, ++ uint16_t offset, + bool is_characteristic, + bool prep_authorize) + { +@@ -2297,33 +2315,37 @@ static struct pending_op *pending_write_new(struct btd_device *device, + op->data.iov_base = (uint8_t *) value; + op->data.iov_len = len; + +- op->device = device; ++ op->att = bt_att_ref(att); + op->owner_queue = owner_queue; + op->attrib = attrib; + op->id = id; + op->offset = offset; +- op->link_type = link_type; ++ op->link_type = bt_att_get_link_type(att); + op->is_characteristic = is_characteristic; + op->prep_authorize = prep_authorize; + queue_push_tail(owner_queue, op); + ++ bt_att_register_disconnect(att, ++ pending_disconnect_cb, ++ op, NULL); ++ + return op; + } + +-static struct pending_op *send_write(struct btd_device *device, ++static struct pending_op *send_write(struct bt_att *att, + struct gatt_db_attribute *attrib, + GDBusProxy *proxy, + struct queue *owner_queue, + unsigned int id, + const uint8_t *value, size_t len, +- uint16_t offset, uint8_t link_type, ++ uint16_t offset, + bool is_characteristic, + bool prep_authorize) + { + struct pending_op *op; + +- op = pending_write_new(device, owner_queue, attrib, id, value, len, +- offset, link_type, is_characteristic, ++ op = pending_write_new(att, owner_queue, attrib, id, value, len, ++ offset, is_characteristic, + prep_authorize); + + if (g_dbus_proxy_method_call(proxy, "WriteValue", write_setup_cb, +@@ -2439,9 +2461,9 @@ static void acquire_write_reply(DBusMessage *message, void *user_data) + return; + + retry: +- send_write(op->device, op->attrib, chrc->proxy, NULL, op->id, ++ send_write(op->att, op->attrib, chrc->proxy, NULL, op->id, + op->data.iov_base, op->data.iov_len, 0, +- op->link_type, false, false); ++ false, false); + } + + static void acquire_write_setup(DBusMessageIter *iter, void *user_data) +@@ -2462,16 +2484,15 @@ static void acquire_write_setup(DBusMessageIter *iter, void *user_data) + } + + static struct pending_op *acquire_write(struct external_chrc *chrc, +- struct btd_device *device, ++ struct bt_att *att, + struct gatt_db_attribute *attrib, + unsigned int id, +- const uint8_t *value, size_t len, +- uint8_t link_type) ++ const uint8_t *value, size_t len) + { + struct pending_op *op; + +- op = pending_write_new(device, NULL, attrib, id, value, len, 0, +- link_type, false, false); ++ op = pending_write_new(att, NULL, attrib, id, value, ++ len, 0, false, false); + + if (g_dbus_proxy_method_call(chrc->proxy, "AcquireWrite", + acquire_write_setup, +@@ -2737,8 +2758,8 @@ static void desc_read_cb(struct gatt_db_attribute *attrib, + goto fail; + } + +- if (send_read(device, attrib, desc->proxy, desc->pending_reads, id, +- offset, bt_att_get_link_type(att))) ++ if (send_read(att, attrib, desc->proxy, desc->pending_reads, id, ++ offset)) + return; + + fail: +@@ -2769,10 +2790,9 @@ static void desc_write_cb(struct gatt_db_attribute *attrib, + if (opcode == BT_ATT_OP_PREP_WRITE_REQ) { + if (!device_is_trusted(device) && !desc->prep_authorized && + desc->req_prep_authorization) +- send_write(device, attrib, desc->proxy, ++ send_write(att, attrib, desc->proxy, + desc->pending_writes, id, value, len, +- offset, bt_att_get_link_type(att), +- false, true); ++ offset, false, true); + else + gatt_db_attribute_write_result(attrib, id, 0); + +@@ -2782,9 +2802,8 @@ static void desc_write_cb(struct gatt_db_attribute *attrib, + if (opcode == BT_ATT_OP_EXEC_WRITE_REQ) + desc->prep_authorized = false; + +- if (send_write(device, attrib, desc->proxy, desc->pending_writes, id, +- value, len, offset, bt_att_get_link_type(att), false, +- false)) ++ if (send_write(att, attrib, desc->proxy, desc->pending_writes, id, ++ value, len, offset, false, false)) + return; + + fail: +@@ -2863,8 +2882,8 @@ static void chrc_read_cb(struct gatt_db_attribute *attrib, + goto fail; + } + +- if (send_read(device, attrib, chrc->proxy, chrc->pending_reads, id, +- offset, bt_att_get_link_type(att))) ++ if (send_read(att, attrib, chrc->proxy, chrc->pending_reads, id, ++ offset)) + return; + + fail: +@@ -2902,9 +2921,9 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib, + if (opcode == BT_ATT_OP_PREP_WRITE_REQ) { + if (!device_is_trusted(device) && !chrc->prep_authorized && + chrc->req_prep_authorization) +- send_write(device, attrib, chrc->proxy, queue, ++ send_write(att, attrib, chrc->proxy, queue, + id, value, len, offset, +- bt_att_get_link_type(att), true, true); ++ true, true); + else + gatt_db_attribute_write_result(attrib, id, 0); + +@@ -2925,13 +2944,12 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib, + } + + if (g_dbus_proxy_get_property(chrc->proxy, "WriteAcquired", &iter)) { +- if (acquire_write(chrc, device, attrib, id, value, len, +- bt_att_get_link_type(att))) ++ if (acquire_write(chrc, att, attrib, id, value, len)) + return; + } + +- if (send_write(device, attrib, chrc->proxy, queue, id, value, len, +- offset, bt_att_get_link_type(att), false, false)) ++ if (send_write(att, attrib, chrc->proxy, queue, id, value, len, ++ offset, false, false)) + return; + + fail: +-- +2.27.0 + diff --git a/bluez.spec b/bluez.spec index b853988..4ab4cc8 100644 --- a/bluez.spec +++ b/bluez.spec @@ -1,7 +1,7 @@ Name: bluez Summary: Bluetooth utilities Version: 5.54 -Release: 10 +Release: 11 License: GPLv2+ URL: http://www.bluez.org/ Source0: http://www.kernel.org/pub/linux/bluetooth/bluez-%{version}.tar.xz @@ -24,6 +24,7 @@ Patch0008: backport-media-rename-local-function-conflicting-with-pause-2. Patch6000: backport-CVE-2020-27153.patch Patch6001: backport-0001-CVE-2021-3658.patch Patch6002: backport-0002-CVE-2021-3658.patch +Patch6003: backport-CVE-2021-43400.patch BuildRequires: dbus-devel >= 1.6 libell-devel >= 0.28 autoconf BuildRequires: glib2-devel libical-devel readline-devel @@ -180,6 +181,12 @@ make check %{_mandir}/man8/* %changelog +* Sat Feb 12 2022 xingxing - 5.54-11 +- Type:CVE +- CVE:CVE-2021-43400 +- SUG:NA +- DESC:fix CVE-2021-43400 + * Thu Feb 13 2022 wangkerong - 5.54-10 - DESC:fix an error in logs during bluez installation or uninstallation -- Gitee