
CVE-2022-25258 - Exploit de demonstração visando o manipulador de descritor OS do gadget USB
O Subsistema de Gadget USB inclui problemas de segurança na seção de manipulação de descritores de SO da função composite_setup (composite.c). O processamento de mensagens de solicitação de transferência de controle adequadamente criadas resulta em falha do dispositivo devido a desreferência de ponteiro nulo ou corrupção de memória.
A seção de manipulação de descritores de SO do composite_setup para destinatário de interface é implementada da seguinte forma.
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;
A variável interface é derivada de w_value e posteriormente utilizada para indexar o array usb_configuration->interface nas funções count_ext_prop, len_ext_prop e fill_ext_prop. Como o array c->interface tem o tamanho de MAX_CONFIG_INTERFACES (16) elementos e a variável interface não é validada nem na seção de manipulação de descritores de SO do composite_setup nem nas funções chamadas, isso permite que um atacante indexe o array c->interface além dos limites reais. Caso a variável interface tenha um valor maior ou igual a MAX_CONFIG_INTERFACES, o endpoint deve ser interrompido (stalled).
Em certos casos, dependendo do conteúdo real da memória, indexar além do array c->interface pode desencadear um estouro de buffer do req->buf via fill_ext_prop quando wLength for maior que 0x0A. Se a soma de ext_prop->name_len, ext_prop->data_len, 14 e 10 estourar o int, a condição count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ não seria atendida, permitindo estouro via memcpy em usb_ext_prop_put_binary. No entanto, a probabilidade de tal situação parece bastante baixa.
Além disso, as funções count_ext_prop, len_ext_prop e fill_ext_prop não possuem validação se o *usb_function recuperado do array c->interface é realmente válido, resultando em desreferência de ponteiro nulo. Quando o ponteiro usb_function recuperado é nulo, o endpoint deve ser interrompido (stalled).
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;
}
Dispositivos Linux (e Android) que expõem gadgets USB com suporte a descritores de SO podem ser arbitrariamente quebrados por um host malicioso por meio de uma única mensagem de transferência de controle.
Uma correção abordando o problema descrito foi aceita e agora está disponível nas versões de kernel suportadas. Para mais informações, consulte o link abaixo.