
CVE-2022-25258 - USBガジェットのOSディスクリプタハンドラを標的としたデモエクスプロイト
USB Gadget サブシステムには、composite_setup 関数 (composite.c) の OS ディスクリプタ処理セクションにセキュリティ上の問題が含まれています。巧妙に細工された制御転送要求メッセージを処理すると、null ポインタ参照またはメモリ破損によってデバイスがクラッシュします。
interface レシピエント向けの 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) 個の要素を持ちますが、composite_setup の OS ディスクリプタ処理セクションでも呼び出される関数内でも interface 変数が検証されないため、攻撃者は c->interface 配列を実際の境界を超えてインデックスすることができます。interface 変数が MAX_CONFIG_INTERFACES 以上の場合、エンドポイントをストールすべきです。
特定の状況では、実際のメモリ内容によって、c->interface 配列を越えたインデックス操作が、wLength が 0x0A より大きい場合に fill_ext_prop を介して req->buf のバッファオーバーフローを引き起こす可能性があります。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 が実際に有効かどうかの検証を欠いており、null ポインタ参照が発生します。取得した usb_function ポインタが null の場合、エンドポイントをストールすべきです。
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) デバイスは、悪意のあるホストによる単一の制御転送メッセージによって任意にクラッシュさせられる可能性があります。
記載された問題に対処するパッチは受理され、サポートされているカーネルバージョンで利用可能になりました。詳細については、以下のリンクを参照してください。