diff mbox series

[BlueZ,2/2] shared/gatt-server: Fix heap overflow when appending prepare writes

Message ID 20211112220538.310085-2-luiz.dentz@gmail.com (mailing list archive)
State Accepted
Delegated to: Luiz Von Dentz
Headers show
Series [BlueZ,1/2] sdpd: Fix leaking buffers stored in cstates cache | expand

Checks

Context Check Description
tedd_an/checkpatch warning [BlueZ,2/2] shared/gatt-server: Fix heap overflow when appending prepare writes WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line) #89: Fixes https://github.com/bluez/bluez/security/advisories/GHSA-479m-xcq5-9g2q /github/workspace/src/12617367.patch total: 0 errors, 1 warnings, 40 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12617367.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS.
tedd_an/gitlint success Gitlint PASS

Commit Message

Luiz Augusto von Dentz Nov. 12, 2021, 10:05 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

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 mbox series

Patch

diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index dc4e681c9..9beec44be 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;