fix CVE-2021-43400
This commit is contained in:
parent
d6544c2992
commit
ece5cc750d
336
backport-CVE-2021-43400.patch
Normal file
336
backport-CVE-2021-43400.patch
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
From 838c0dc7641e1c991c0f3027bf94bee4606012f8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernie Conrad <bernie@allthenticate.net>
|
||||||
|
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
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
Name: bluez
|
Name: bluez
|
||||||
Summary: Bluetooth utilities
|
Summary: Bluetooth utilities
|
||||||
Version: 5.54
|
Version: 5.54
|
||||||
Release: 10
|
Release: 11
|
||||||
License: GPLv2+
|
License: GPLv2+
|
||||||
URL: http://www.bluez.org/
|
URL: http://www.bluez.org/
|
||||||
Source0: http://www.kernel.org/pub/linux/bluetooth/bluez-%{version}.tar.xz
|
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
|
Patch6000: backport-CVE-2020-27153.patch
|
||||||
Patch6001: backport-0001-CVE-2021-3658.patch
|
Patch6001: backport-0001-CVE-2021-3658.patch
|
||||||
Patch6002: backport-0002-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: dbus-devel >= 1.6 libell-devel >= 0.28 autoconf
|
||||||
BuildRequires: glib2-devel libical-devel readline-devel
|
BuildRequires: glib2-devel libical-devel readline-devel
|
||||||
@ -180,6 +181,12 @@ make check
|
|||||||
%{_mandir}/man8/*
|
%{_mandir}/man8/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Feb 11 2022 xingxing <xingxing9@h-partners.com> - 5.54-11
|
||||||
|
- Type:CVE
|
||||||
|
- CVE:CVE-2021-43400
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:fix CVE-2021-43400
|
||||||
|
|
||||||
* Thu Jan 13 2022 wangkerong <wangkerong@huawei.com> - 5.54-10
|
* Thu Jan 13 2022 wangkerong <wangkerong@huawei.com> - 5.54-10
|
||||||
- DESC:fix an error in logs during bluez installation or uninstallation
|
- DESC:fix an error in logs during bluez installation or uninstallation
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user