diff -Nru bluez-5.48/debian/changelog bluez-5.48/debian/changelog --- bluez-5.48/debian/changelog 2020-03-23 12:26:28.000000000 +0000 +++ bluez-5.48/debian/changelog 2021-06-09 15:12:47.000000000 +0000 @@ -1,3 +1,16 @@ +bluez (5.48-0ubuntu3.5) bionic-security; urgency=medium + + * SECURITY UPDATE: secure pairing passkey brute force + - debian/patches/CVE-2020-26558.patch: fix not properly checking for + secure flags in src/shared/att-types.h, src/shared/gatt-server.c. + - CVE-2020-26558 + * SECURITY UPDATE: DoS or code execution via double-free + - debian/patches/CVE-2020-27153.patch: fix possible crash on disconnect + in src/shared/att.c. + - CVE-2020-27153 + + -- Marc Deslauriers Wed, 09 Jun 2021 11:12:47 -0400 + bluez (5.48-0ubuntu3.4) bionic-security; urgency=medium * SECURITY UPDATE: privilege escalation via improper access control diff -Nru bluez-5.48/debian/patches/CVE-2020-26558.patch bluez-5.48/debian/patches/CVE-2020-26558.patch --- bluez-5.48/debian/patches/CVE-2020-26558.patch 1970-01-01 00:00:00.000000000 +0000 +++ bluez-5.48/debian/patches/CVE-2020-26558.patch 2021-06-09 15:08:03.000000000 +0000 @@ -0,0 +1,88 @@ +Backport of: + +From 00da0fb4972cf59e1c075f313da81ea549cb8738 Mon Sep 17 00:00:00 2001 +From: Luiz Augusto von Dentz +Date: Tue, 2 Mar 2021 11:38:33 -0800 +Subject: shared/gatt-server: Fix not properly checking for secure flags + +When passing the mask to check_permissions all valid permissions for +the operation must be set including BT_ATT_PERM_SECURE flags. +--- + src/shared/att-types.h | 8 ++++++++ + src/shared/gatt-server.c | 25 +++++++------------------ + 2 files changed, 15 insertions(+), 18 deletions(-) + +--- a/src/shared/att-types.h ++++ b/src/shared/att-types.h +@@ -132,6 +132,14 @@ struct bt_att_pdu_error_rsp { + #define BT_ATT_PERM_WRITE_SECURE 0x0200 + #define BT_ATT_PERM_SECURE (BT_ATT_PERM_READ_SECURE | \ + BT_ATT_PERM_WRITE_SECURE) ++#define BT_ATT_PERM_READ_MASK (BT_ATT_PERM_READ | \ ++ BT_ATT_PERM_READ_AUTHEN | \ ++ BT_ATT_PERM_READ_ENCRYPT | \ ++ BT_ATT_PERM_READ_SECURE) ++#define BT_ATT_PERM_WRITE_MASK (BT_ATT_PERM_WRITE | \ ++ BT_ATT_PERM_WRITE_AUTHEN | \ ++ BT_ATT_PERM_WRITE_ENCRYPT | \ ++ BT_ATT_PERM_WRITE_SECURE) + + /* GATT Characteristic Properties Bitfield values */ + #define BT_GATT_CHRC_PROP_BROADCAST 0x01 +--- a/src/shared/gatt-server.c ++++ b/src/shared/gatt-server.c +@@ -427,9 +427,7 @@ static void process_read_by_type(struct + return; + } + +- ecode = check_permissions(server, attr, BT_ATT_PERM_READ | +- BT_ATT_PERM_READ_AUTHEN | +- BT_ATT_PERM_READ_ENCRYPT); ++ ecode = check_permissions(server, attr, BT_ATT_PERM_READ_MASK); + if (ecode) + goto error; + +@@ -782,9 +780,7 @@ static void write_cb(uint8_t opcode, con + (opcode == BT_ATT_OP_WRITE_REQ) ? "Req" : "Cmd", + handle); + +- ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE | +- BT_ATT_PERM_WRITE_AUTHEN | +- BT_ATT_PERM_WRITE_ENCRYPT); ++ ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE_MASK); + if (ecode) + goto error; + +@@ -888,9 +884,7 @@ static void handle_read_req(struct bt_ga + opcode == BT_ATT_OP_READ_BLOB_REQ ? "Blob " : "", + handle); + +- ecode = check_permissions(server, attr, BT_ATT_PERM_READ | +- BT_ATT_PERM_READ_AUTHEN | +- BT_ATT_PERM_READ_ENCRYPT); ++ ecode = check_permissions(server, attr, BT_ATT_PERM_READ_MASK); + if (ecode) + goto error; + +@@ -987,9 +981,7 @@ static void read_multiple_complete_cb(st + return; + } + +- ecode = check_permissions(data->server, attr, BT_ATT_PERM_READ | +- BT_ATT_PERM_READ_AUTHEN | +- BT_ATT_PERM_READ_ENCRYPT); ++ ecode = check_permissions(data->server, attr, BT_ATT_PERM_READ_MASK); + if (ecode) { + bt_att_send_error_rsp(data->server->att, + BT_ATT_OP_READ_MULT_REQ, handle, ecode); +@@ -1210,9 +1202,7 @@ static void prep_write_cb(uint8_t opcode + util_debug(server->debug_callback, server->debug_data, + "Prep Write Req - handle: 0x%04x", handle); + +- ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE | +- BT_ATT_PERM_WRITE_AUTHEN | +- BT_ATT_PERM_WRITE_ENCRYPT); ++ ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE_MASK); + if (ecode) + goto error; + diff -Nru bluez-5.48/debian/patches/CVE-2020-27153.patch bluez-5.48/debian/patches/CVE-2020-27153.patch --- bluez-5.48/debian/patches/CVE-2020-27153.patch 1970-01-01 00:00:00.000000000 +0000 +++ bluez-5.48/debian/patches/CVE-2020-27153.patch 2021-06-09 15:08:12.000000000 +0000 @@ -0,0 +1,141 @@ +Backport of: + +From 1cd644db8c23a2f530ddb93cebed7dacc5f5721a Mon Sep 17 00:00:00 2001 +From: Luiz Augusto von Dentz +Date: Wed, 15 Jul 2020 18:25:37 -0700 +Subject: [PATCH] shared/att: Fix possible crash on disconnect + +If there are pending request while disconnecting they would be notified +but clients may endup being freed in the proccess which will then be +calling bt_att_cancel to cancal its requests causing the following +trace: + +Invalid read of size 4 + at 0x1D894C: enable_ccc_callback (gatt-client.c:1627) + by 0x1D247B: disc_att_send_op (att.c:417) + by 0x1CCC17: queue_remove_all (queue.c:354) + by 0x1D47B7: disconnect_cb (att.c:635) + by 0x1E0707: watch_callback (io-glib.c:170) + by 0x48E963B: g_main_context_dispatch (in /usr/lib/libglib-2.0.so.0.6400.4) + by 0x48E9AC7: ??? (in /usr/lib/libglib-2.0.so.0.6400.4) + by 0x48E9ECF: g_main_loop_run (in /usr/lib/libglib-2.0.so.0.6400.4) + by 0x1E0E97: mainloop_run (mainloop-glib.c:79) + by 0x1E13B3: mainloop_run_with_signal (mainloop-notify.c:201) + by 0x12BC3B: main (main.c:770) + Address 0x7d40a28 is 24 bytes inside a block of size 32 free'd + at 0x484A2E0: free (vg_replace_malloc.c:540) + by 0x1CCC17: queue_remove_all (queue.c:354) + by 0x1CCC83: queue_destroy (queue.c:73) + by 0x1D7DD7: bt_gatt_client_free (gatt-client.c:2209) + by 0x16497B: batt_free (battery.c:77) + by 0x16497B: batt_remove (battery.c:286) + by 0x1A0013: service_remove (service.c:176) + by 0x1A9B7B: device_remove_gatt_service (device.c:3691) + by 0x1A9B7B: gatt_service_removed (device.c:3805) + by 0x1CC90B: queue_foreach (queue.c:220) + by 0x1DE27B: notify_service_changed.isra.0.part.0 (gatt-db.c:369) + by 0x1DE387: notify_service_changed (gatt-db.c:361) + by 0x1DE387: gatt_db_service_destroy (gatt-db.c:385) + by 0x1DE3EF: gatt_db_remove_service (gatt-db.c:519) + by 0x1D674F: discovery_op_complete (gatt-client.c:388) + by 0x1D6877: discover_primary_cb (gatt-client.c:1260) + by 0x1E220B: discovery_op_complete (gatt-helpers.c:628) + by 0x1E249B: read_by_grp_type_cb (gatt-helpers.c:730) + by 0x1D247B: disc_att_send_op (att.c:417) + by 0x1CCC17: queue_remove_all (queue.c:354) + by 0x1D47B7: disconnect_cb (att.c:635) +--- + src/shared/att.c | 46 ++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 40 insertions(+), 6 deletions(-) + +--- a/src/shared/att.c ++++ b/src/shared/att.c +@@ -61,6 +61,7 @@ struct bt_att { + struct queue *ind_queue; /* Queued ATT protocol indications */ + struct att_send_op *pending_ind; + struct queue *write_queue; /* Queue of PDUs ready to send */ ++ bool in_disc; /* Cleanup queues on disconnect_cb */ + bool writer_active; + + struct queue *notify_list; /* List of registered callbacks */ +@@ -210,8 +211,10 @@ static void destroy_att_send_op(void *da + free(op); + } + +-static void cancel_att_send_op(struct att_send_op *op) ++static void cancel_att_send_op(void *data) + { ++ struct att_send_op *op = data; ++ + if (op->destroy) + op->destroy(op->user_data); + +@@ -570,11 +573,6 @@ static bool disconnect_cb(struct io *io, + io_destroy(att->io); + att->io = NULL; + +- /* Notify request callbacks */ +- queue_remove_all(att->req_queue, NULL, NULL, disc_att_send_op); +- queue_remove_all(att->ind_queue, NULL, NULL, disc_att_send_op); +- queue_remove_all(att->write_queue, NULL, NULL, disc_att_send_op); +- + if (att->pending_req) { + disc_att_send_op(att->pending_req); + att->pending_req = NULL; +@@ -587,6 +585,15 @@ static bool disconnect_cb(struct io *io, + + bt_att_ref(att); + ++ att->in_disc = true; ++ ++ /* Notify request callbacks */ ++ queue_remove_all(att->req_queue, NULL, NULL, disc_att_send_op); ++ queue_remove_all(att->ind_queue, NULL, NULL, disc_att_send_op); ++ queue_remove_all(att->write_queue, NULL, NULL, disc_att_send_op); ++ ++ att->in_disc = false; ++ + queue_foreach(att->disconn_list, disconn_handler, INT_TO_PTR(err)); + + bt_att_unregister_all(att); +@@ -1287,6 +1294,30 @@ static bool match_op_id(const void *a, c + return op->id == id; + } + ++static bool bt_att_disc_cancel(struct bt_att *att, unsigned int id) ++{ ++ struct att_send_op *op; ++ ++ op = queue_find(att->req_queue, match_op_id, UINT_TO_PTR(id)); ++ if (op) ++ goto done; ++ ++ op = queue_find(att->ind_queue, match_op_id, UINT_TO_PTR(id)); ++ if (op) ++ goto done; ++ ++ op = queue_find(att->write_queue, match_op_id, UINT_TO_PTR(id)); ++ ++done: ++ if (!op) ++ return false; ++ ++ /* Just cancel since disconnect_cb will be cleaning up */ ++ cancel_att_send_op(op); ++ ++ return true; ++} ++ + bool bt_att_cancel(struct bt_att *att, unsigned int id) + { + struct att_send_op *op; +@@ -1306,6 +1337,9 @@ bool bt_att_cancel(struct bt_att *att, u + return true; + } + ++ if (att->in_disc) ++ return bt_att_disc_cancel(att, id); ++ + op = queue_remove_if(att->req_queue, match_op_id, UINT_TO_PTR(id)); + if (op) + goto done; diff -Nru bluez-5.48/debian/patches/series bluez-5.48/debian/patches/series --- bluez-5.48/debian/patches/series 2020-03-23 12:26:23.000000000 +0000 +++ bluez-5.48/debian/patches/series 2021-06-09 15:12:15.000000000 +0000 @@ -18,3 +18,5 @@ CVE-2020-0556-2.patch CVE-2020-0556-3.patch CVE-2020-0556-4.patch +CVE-2020-26558.patch +CVE-2020-27153.patch