62 lines
1.9 KiB
Diff
62 lines
1.9 KiB
Diff
From 591c546c536b42bef696d027f64aa22434f8c3f0 Mon Sep 17 00:00:00 2001
|
|
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
|
|
Date: Tue, 8 Jun 2021 16:46:49 -0700
|
|
Subject: [PATCH] shared/gatt-server: Fix heap overflow when appending prepare
|
|
writes
|
|
|
|
The code shall check if the prepare writes would append more the
|
|
allowed maximum attribute length.
|
|
|
|
Fixes https://github.com/bluez/bluez/security/advisories/GHSA-479m-xcq5-9g2q
|
|
---
|
|
src/shared/gatt-server.c | 22 ++++++++++++++++++++++
|
|
1 file changed, 22 insertions(+)
|
|
|
|
diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
|
|
index dc4e681c9c..9beec44bed 100644
|
|
--- a/src/shared/gatt-server.c
|
|
+++ b/src/shared/gatt-server.c
|
|
@@ -779,6 +779,20 @@ static uint8_t authorize_req(struct bt_gatt_server *server,
|
|
server->authorize_data);
|
|
}
|
|
|
|
+static uint8_t check_length(uint16_t length, uint16_t offset)
|
|
+{
|
|
+ if (length > BT_ATT_MAX_VALUE_LEN)
|
|
+ return BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
|
|
+
|
|
+ if (offset > BT_ATT_MAX_VALUE_LEN)
|
|
+ return BT_ATT_ERROR_INVALID_OFFSET;
|
|
+
|
|
+ if (length + offset > BT_ATT_MAX_VALUE_LEN)
|
|
+ return BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static void write_cb(struct bt_att_chan *chan, uint8_t opcode, const void *pdu,
|
|
uint16_t length, void *user_data)
|
|
{
|
|
@@ -809,6 +823,10 @@ static void write_cb(struct bt_att_chan *chan, uint8_t opcode, const void *pdu,
|
|
(opcode == BT_ATT_OP_WRITE_REQ) ? "Req" : "Cmd",
|
|
handle);
|
|
|
|
+ ecode = check_length(length, 0);
|
|
+ if (ecode)
|
|
+ goto error;
|
|
+
|
|
ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE_MASK);
|
|
if (ecode)
|
|
goto error;
|
|
@@ -1299,6 +1317,10 @@ static void prep_write_cb(struct bt_att_chan *chan, uint8_t opcode,
|
|
util_debug(server->debug_callback, server->debug_data,
|
|
"Prep Write Req - handle: 0x%04x", handle);
|
|
|
|
+ ecode = check_length(length, offset);
|
|
+ if (ecode)
|
|
+ goto error;
|
|
+
|
|
ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE_MASK);
|
|
if (ecode)
|
|
goto error;
|