diff options
author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2012-06-20 14:27:43 -0300 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2012-06-27 15:49:18 +0300 |
commit | 2f8cd0cb7eb9a4bceb1cec221ccd21f76d66f318 (patch) | |
tree | 00f40acac4e8fbd3a65a12d120aad977dedd6345 /attrib | |
parent | f0478f073aff412552b568df96b2e6a5fd68c474 (diff) |
ATT: Avoid invalid memory access for large PDU
This patch avoids invalid memory access when decoding ATT read response
PDUs. The ATT_MTU value is a per ATT Bearer value defined by the higher
layer specification.
Diffstat (limited to 'attrib')
-rw-r--r-- | attrib/att.c | 17 | ||||
-rw-r--r-- | attrib/att.h | 2 | ||||
-rw-r--r-- | attrib/gatttool.c | 7 | ||||
-rw-r--r-- | attrib/interactive.c | 6 |
4 files changed, 19 insertions, 13 deletions
diff --git a/attrib/att.c b/attrib/att.c index c8e2e1d9..0550ac13 100644 --- a/attrib/att.c +++ b/attrib/att.c @@ -681,22 +681,23 @@ uint16_t enc_read_blob_resp(uint8_t *value, int vlen, uint16_t offset, return vlen + 1; } -uint16_t dec_read_resp(const uint8_t *pdu, int len, uint8_t *value, int *vlen) +ssize_t dec_read_resp(const uint8_t *pdu, int len, uint8_t *value, int vlen) { if (pdu == NULL) - return 0; + return -EINVAL; - if (value == NULL || vlen == NULL) - return 0; + if (value == NULL) + return -EINVAL; if (pdu[0] != ATT_OP_READ_RESP) - return 0; + return -EINVAL; - memcpy(value, pdu + 1, len - 1); + if (vlen < (len - 1)) + return -ENOBUFS; - *vlen = len - 1; + memcpy(value, pdu + 1, len - 1); - return len; + return len - 1; } uint16_t enc_error_resp(uint8_t opcode, uint16_t handle, uint8_t status, diff --git a/attrib/att.h b/attrib/att.h index 144513fe..1c1102a9 100644 --- a/attrib/att.h +++ b/attrib/att.h @@ -234,7 +234,7 @@ uint16_t dec_read_blob_req(const uint8_t *pdu, int len, uint16_t *handle, uint16_t enc_read_resp(uint8_t *value, int vlen, uint8_t *pdu, int len); uint16_t enc_read_blob_resp(uint8_t *value, int vlen, uint16_t offset, uint8_t *pdu, int len); -uint16_t dec_read_resp(const uint8_t *pdu, int len, uint8_t *value, int *vlen); +ssize_t dec_read_resp(const uint8_t *pdu, int len, uint8_t *value, int vlen); uint16_t enc_error_resp(uint8_t opcode, uint16_t handle, uint8_t status, uint8_t *pdu, int len); uint16_t enc_find_info_req(uint16_t start, uint16_t end, uint8_t *pdu, int len); diff --git a/attrib/gatttool.c b/attrib/gatttool.c index 8a43ec1c..c70b1d65 100644 --- a/attrib/gatttool.c +++ b/attrib/gatttool.c @@ -227,14 +227,17 @@ static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { uint8_t value[ATT_MAX_MTU]; - int i, vlen; + ssize_t vlen; + int i; if (status != 0) { g_printerr("Characteristic value/descriptor read failed: %s\n", att_ecode2str(status)); goto done; } - if (!dec_read_resp(pdu, plen, value, &vlen)) { + + vlen = dec_read_resp(pdu, plen, value, sizeof(value)); + if (vlen < 0) { g_printerr("Protocol error\n"); goto done; } diff --git a/attrib/interactive.c b/attrib/interactive.c index 0a01cdf6..1cdbfefc 100644 --- a/attrib/interactive.c +++ b/attrib/interactive.c @@ -275,7 +275,8 @@ static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { uint8_t value[ATT_MAX_MTU]; - int i, vlen; + ssize_t vlen; + int i; if (status != 0) { printf("Characteristic value/descriptor read failed: %s\n", @@ -283,7 +284,8 @@ static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen, return; } - if (!dec_read_resp(pdu, plen, value, &vlen)) { + vlen = dec_read_resp(pdu, plen, value, sizeof(value)); + if (vlen < 0) { printf("Protocol error\n"); return; } |