
CVE-2022-25258 - استغلال تجريبي يستهدف معالج واصف OS لجهاز USB gadget
يحتوي نظام USB Gadget الفرعي (USB Gadget Subsystem) على ثغرات أمنية في قسم معالجة واصفات نظام التشغيل (OS descriptor) داخل دالة composite_setup (composite.c). تؤدي معالجة رسائل طلبات نقل التحكم المُصاغة بدقة إلى تعطل الجهاز بسبب إلغاء مرجعية مؤشر فارغ (null pointer dereference) أو تلف في الذاكرة.
قسم معالجة واصفات نظام التشغيل في composite_setup لمستلم الواجهة (interface recipient) مُنفَّذ كما يلي.
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 ويُستخدم لاحقًا لفهرسة مصفوفة usb_configuration->interface في الدوال count_ext_prop و len_ext_prop و fill_ext_prop. وبما أن مصفوفة c->interface حجمها MAX_CONFIG_INTERFACES (16) عنصرًا، وأن متغير interface لا يتم التحقق منه لا في قسم معالجة واصفات نظام التشغيل في composite_setup ولا في الدوال المُستدعاة، فإن ذلك يسمح للمهاجم بفهرسة مصفوفة c->interface خارج حدودها الفعلية. في حال كانت قيمة متغير interface أكبر من أو تساوي MAX_CONFIG_INTERFACES، يجب إيقاف نقطة النهاية (endpoint) باستخدام حالة stall.
في حالات معينة، واعتمادًا على محتوى الذاكرة الفعلي، قد تؤدي الفهرسة خارج حدود مصفوفة c->interface إلى تجاوز سعة المخزن المؤقت req->buf عبر fill_ext_prop عندما تكون wLength أكبر من 0x0A. وإذا تجاوز مجموع ext_prop->name_len و ext_prop->data_len و 14 و 10 حد نوع int، فلن يتحقق شرط count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ، مما يسمح بتجاوز السعة عبر memcpy في usb_ext_prop_put_binary. ومع ذلك، يبدو احتمال حدوث مثل هذا الموقف منخفضًا جدًا.
علاوةً على ذلك، تفتقر الدوال count_ext_prop و len_ext_prop و fill_ext_prop إلى التحقق من صحة مؤشر *usb_function المستخرج من مصفوفة c->interface، مما يؤدي إلى إلغاء مرجعية مؤشر فارغ (null pointer dereference). عندما يكون مؤشر 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;
}
أجهزة Linux (وAndroid) التي تعرض أدوات USB (usb gadgets) مع دعم واصفات نظام التشغيل يمكن أن يتعطلها مضيف خبيث بشكل تعسفي عبر رسالة نقل تحكم واحدة.
تم قبول تصحيح يعالج المشكلة الموصوفة وهو متاح الآن في إصدارات النواة المدعومة. لمزيد من المعلومات، راجع الرابط أدناه.