USB小工具子系统在composite_setup函数(composite.c)的OS描述符处理部分存在安全问题。处理精心构造的控制传输请求消息会因空指针解引用或内存损坏而导致设备崩溃。
composite_setup中针对接口接收者的OS描述符处理部分实现如下。
case USB_RECIP_INTERFACE:
if (w_index != 0x5 || (w_value >> 8))
break;
interface = w_value & 0xFF;
buf[6] = w_index;
count = count_ext_prop(os_desc_cfg,
interface);
put_unaligned_le16(count, buf + 8);
count = len_ext_prop(os_desc_cfg,
interface);
put_unaligned_le32(count, buf);
value = w_length;
if (w_length > 0x0A) {
value = fill_ext_prop(os_desc_cfg,
interface, buf);
if (value >= 0)
value = min_t(u16, w_length, value);
}
break;
interface变量来源于w_value,随后用于在count_ext_prop、len_ext_prop和fill_ext_prop函数中索引usb_configuration->interface数组。由于c->interface数组的大小为MAX_CONFIG_INTERFACES(16)个元素,且interface变量在composite_setup的OS描述符处理部分或被调用的函数中均未经验证,攻击者可以利用此漏洞越界索引c->interface数组。当interface变量的值大于或等于MAX_CONFIG_INTERFACES时,端点应被停止(STALL)。
在某些情况下,根据实际内存内容,越界索引c->interface数组可能通过fill_ext_prop触发req->buf的缓冲区溢出(当wLength大于0x0A时)。如果ext_prop->name_len、ext_prop->data_len、14和10的和在int类型中溢出,则条件count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ将不满足,从而允许通过usb_ext_prop_put_binary中的memcpy造成溢出。不过出现这种情况的可能性似乎很低。
此外,count_ext_prop、len_ext_prop和fill_ext_prop函数缺少对从c->interface数组获取的*usb_function是否有效的验证,导致空指针解引用。当检索到的usb_function指针为空时,端点应被停止(STALL)。
static int count_ext_prop(struct usb_configuration *c, int interface)
{
struct usb_function *f;
int j;
f = c->interface[interface];
for (j = 0; j < f->os_desc_n; ++j) {
struct usb_os_desc *d;
if (interface != f->os_desc_table[j].if_id)
continue;
d = f->os_desc_table[j].os_desc;
if (d && d->ext_compat_id)
return d->ext_prop_count;
}
return 0;
}
暴露了带有OS描述符支持的USB小工具的Linux(和Android)设备可能因单个控制传输消息而受到恶意主机的攻击,导致任意崩溃。
一个解决所述问题的补丁已被接受,现在可用于支持的内核版本。更多信息请参阅以下链接。