2023.09.17
CVE-2022-20410 | A-205570663 | ID | High | 10, 11, 12, 12L, 13 |
---|
patch

diff --git a/system/stack/avrc/avrc_pars_ct.cc b/system/stack/avrc/avrc_pars_ct.cc
index 12aee4c..a571042 100644
--- a/system/stack/avrc/avrc_pars_ct.cc
+++ b/system/stack/avrc/avrc_pars_ct.cc
@@ -237,7 +237,7 @@
}
BE_STREAM_TO_UINT8(pdu, p);
uint16_t pkt_len;
- int min_len = 0;
+ uint16_t min_len = 0;
/* read the entire packet len */
BE_STREAM_TO_UINT16(pkt_len, p);
@@ -380,8 +380,14 @@
/* Parse the name now */
BE_STREAM_TO_UINT16(attr_entry->name.charset_id, p);
BE_STREAM_TO_UINT16(attr_entry->name.str_len, p);
+ if (static_cast<uint16_t>(min_len + attr_entry->name.str_len) <
+ min_len) {
+ // Check for overflow
+ android_errorWriteLog(0x534e4554, "205570663");
+ }
+ if (pkt_len - min_len < attr_entry->name.str_len)
+ goto browse_length_error;
min_len += attr_entry->name.str_len;
- if (pkt_len < min_len) goto browse_length_error;
attr_entry->name.p_str = (uint8_t*)osi_malloc(
attr_entry->name.str_len * sizeof(uint8_t));
BE_STREAM_TO_ARRAY(p, attr_entry->name.p_str,
@@ -444,8 +450,14 @@
BE_STREAM_TO_UINT32(attr_entry->attr_id, p);
BE_STREAM_TO_UINT16(attr_entry->name.charset_id, p);
BE_STREAM_TO_UINT16(attr_entry->name.str_len, p);
+ if (static_cast<uint16_t>(min_len + attr_entry->name.str_len) <
+ min_len) {
+ // Check for overflow
+ android_errorWriteLog(0x534e4554, "205570663");
+ }
+ if (pkt_len - min_len < attr_entry->name.str_len)
+ goto browse_length_error;
min_len += attr_entry->name.str_len;
- if (pkt_len < min_len) goto browse_length_error;
attr_entry->name.p_str =
(uint8_t*)osi_malloc(attr_entry->name.str_len * sizeof(uint8_t));
BE_STREAM_TO_ARRAY(p, attr_entry->name.p_str, attr_entry->name.str_len);
@@ -815,8 +827,12 @@
BE_STREAM_TO_UINT32(p_attrs[i].attr_id, p);
BE_STREAM_TO_UINT16(p_attrs[i].name.charset_id, p);
BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p);
- min_len += p_attrs[i].name.str_len;
- if (len < min_len) {
+ if (static_cast<uint16_t>(min_len + p_attrs[i].name.str_len) <
+ min_len) {
+ // Check for overflow
+ android_errorWriteLog(0x534e4554, "205570663");
+ }
+ if (len - min_len < p_attrs[i].name.str_len) {
for (int j = 0; j < i; j++) {
osi_free(p_attrs[j].name.p_str);
}
@@ -824,6 +840,7 @@
p_result->get_attrs.num_attrs = 0;
goto length_error;
}
+ min_len += p_attrs[i].name.str_len;
if (p_attrs[i].name.str_len > 0) {
p_attrs[i].name.p_str =
(uint8_t*)osi_calloc(p_attrs[i].name.str_len);
分析
下图为hanzinuo大神的PPT,看这一页很容易理解:
min_len
是一个uint16_t
类型的变量,初始值为0,然后+8- 从packet解析得到变量
attr_entyr->name.str_len
,该变量的取值范围是0~UINT16_MAX
- 将
attr_entyr->name.str_len
的值添加到min_len
,因为这里没有做判断,所以如果attr_entyr->name.str_len
很大,那么就可能导致整数溢出 - 下一行的if判断中,是想要判断packet是否
>=min_len
,如果满足就继续往下走。而前面如果发生整数溢出,那么min_len
变得很小,就会绕过这个检查 - 接着,malloc分配的chunk的大小是
attr_entyr->name.str_len
,会大于packet的实际长度,就会导致OOB Read

再来看看patch,好像和ppt里有点对不上?
不过单看patch也能看明白:在三处BE_STREAM_TO_UINT16(p_attrs[i].name.str_len, p);
后面都添加了长度检查,这个不难理解。
我唯一不理解的就是第一处patch把一个min_len
从int改成了uint_16
?这是为啥?改错了?我看了一下main分支的代码,所有min_len
都改成了uint32_t
。