ترجمة آلية لم تُراجَع بعد. النص الإنجليزي هو المرجع في حال الاختلاف.
الملخص
في نواة Linux، تم حل الثغرة التالية: io_uring/waitid: امتلاك الطلب قبل مسح ->head. تأخذ io_waitid_remove_wq() قفل طابور الانتظار فقط إذا تم تعيين ->head. تقوم io_waitid_wait() بمسح ->head أولاً، قبل أن تحاول أن تصبح مالكة للطلب عن طريق زيادة ->refs. إذا كان شخص آخر يمتلك الطلب في تلك اللحظة، فلا شيء يمنعه من إكمال الطلب بينما لا يزال معالج التنبيه على وشك لمسه: CPU0 (io_waitid_wait) CPU1 (io_waitid, holds a ref) list_del_init(&wait->entry) smp_store_release(&iw->head, NULL) __do_wait() finds another child io_waitid_remove_wq() // ->head == NULL, no locking io_waitid_finish(), IOU_COMPLETE // request freed and reused atomic_fetch_inc(&iw->refs). نفس الشيء ينطبق على __io_waitid_cancel() إذا طالبت بالطلب في تلك النافذة الزمنية. ->refs هو جزء من بيانات كل رمز تشغيل (opcode) للطلب، لذا فهذا يزيد أي شيء يحتفظ به المستخدم التالي للطلب هناك. إذا حدث وكان صفرًا، يستنتج المعالج أنه يمتلك الطلب، ويقوم بإدراج io_waitid_cb() في الطابور من أجله. مع بقاء النافذة مفتوحة بسبب تأخير، وإعادة استخدام الطلب لعملية استقبال تنتظر بيانات: BUG: KASAN: slab-use-after-free in __wake_up_common+0x1ca/0x1f0 __wake_up_sync_key+0x36/0x50 sock_def_readable+0xf1/0x420 unix_stream_sendmsg+0x60b/0x1110 Allocated by task 87: io_arm_apoll+0x1ed/0x940 Freed by task 87: __io_submit_flush_completions+0x118d/0x1a10 tctx_task_work_run+0x327/0x950. قم فقط بمسح ->head بمجرد أن يمتلك المعالج الطلب. وإذا لم يفعل، يجد المالك ->head معينًا ويجب عليه انتظار القفل، الذي يحتفظ به المتصل بمعالج الأحداث. حذف العنصر المحذوف بالفعل مرة أخرى يعد أمرًا غير ضار.
المعالجة
المراجع
- مرجعhttps://git.kernel.org/stable/c/bf01da1a9cca4a54e5c30b8344e52c26afb87be7
- مرجعhttps://git.kernel.org/stable/c/8381a912c65b8de16e8a848225c7c5a56b6ea834
- مرجعhttps://git.kernel.org/stable/c/c10ad2813e15186fb51b37a4d17fafddc99e89a5
- مرجعhttps://git.kernel.org/stable/c/c254eec4364b9f4b4cbdce43be3fb4df5a651a70