Use-after-free — dastur xotira obyektini bo‘shatgandan keyin unga saqlanib qolgan pointer yoki reference orqali yana murojaat qiladigan memory safety xatosidir. Ajratgich o‘sha hududni boshqa obyektga berishi mumkin, shuning uchun eski pointer yangi ma’lumotni o‘qiydi yoki buzadi. Native kodda bu crash, ma’lumot sizishi va remote code executionga olib kelishi mumkin.
Xato mexanizmi
Obyektning bir nechta egasi yoki observeri bo‘lsa, bittasi uni ozod qiladi, boshqalari esa lifetime tugaganini bilmaydi. Callback navbatda qolishi, async amal kech tugashi yoki container elementini o‘chirish iteratorni yaroqsiz qilishi mumkin. Multithreadingda bir oqim foydalanayotgan paytda boshqasi free qilishi poyga yaratadi.
char *p = malloc(32);
free(p);
p[0] = 'A'; /* yaroqsiz murojaat */
Oddiy misol darhol ko‘rinsa ham haqiqiy xato ko‘pincha vaqtga bog‘liq. Free qilingan blok hali qayta ishlatilmagan bo‘lsa test “to‘g‘ri” o‘tishi mumkin. Optimized build va boshqa allocation tartibi xatoni namoyon qiladi.
Ekspluatatsiya
Hujumchi heap holatini boshqarib, ozod qilingan joyga tanlangan obyektni joylashtirishga urinadi. Eski pointer virtual function table, callback yoki uzunlik maydonini yangi ma’lumot sifatida talqin qilsa control flow o‘zgarishi mumkin. ASLR, heap hardening va control-flow integrity ekspluatatsiyani qiyinlashtiradi, lekin xatoni tuzatmaydi.
Read-only UAF ham maxfiy ma’lumotni qaytarishi mumkin. Crashdan tashqari noto‘g‘ri authorization obyektiga murojaat yoki boshqa foydalanuvchi ma’lumoti chiqishi ehtimol. Og‘irlik access turi va hujumchi heapni qanchalik boshqara olishiga bog‘liq.
Aniqlash
AddressSanitizer allocation atrofida shadow memory va quarantine ishlatib yaroqsiz accessni aniq stack trace bilan topadi. Valgrind va boshqa dynamic analyzer sekinroq bo‘lsa ham instrumental build talabini kamaytirishi mumkin. Fuzzing turli input va timing bilan yashirin lifetime yo‘lini ochadi.
Allocator freed blokni zaharli pattern bilan to‘ldirishi, quarantine’da ushlab turishi va double free’ni tekshirishi mumkin. Production crash dumpda fault address, allocation/free stack va heap metadata muhim. Faqat crash joyini tuzatish emas, ownership zanjiri topiladi.
Oldini olish
RAII va aniq ownership lifetime’ni scope bilan bog‘laydi. Unique pointer yagona egani, reference counting bo‘lishilgan egalikni ifodalaydi. Weak reference obyektni tirik ushlab turmaydi va ishlatishdan oldin kuchli referencega muvaffaqiyatli aylantiriladi. Reference cycle alohida boshqariladi.
Concurrencyda obyekt free bo‘lishidan oldin barcha o‘quvchi tugashi kerak. Mutex, hazard pointer, epoch reclamation yoki RCU mos modelni beradi. Shunchaki pointerga NULL yozish faqat shu o‘zgaruvchini tozalaydi; boshqa nusxalar dangling bo‘lib qoladi. Memory-safe til ko‘p UAF sinfini type va garbage collection orqali cheklaydi, unsafe interop chegarasi baribir audit qilinadi.
API dizayni
Asinxron API callbackga raw pointer olib, amal tugaguncha uning lifetime’ini kafolatlamasa UAF xavfi tug‘iladi. Token yoki owned handle callback kontekstini tirik ushlab turadi, cancellation esa completion bilan ayni ownership state machine’da raqobatlashadi. GUI’da widget yopilgach navbatdagi event eski obyektga murojaat qilmasligi uchun subscription lifecycle bilan uziladi. Kernel driverda qurilma remove bo‘lganda reference count, pending I/O va interrupt handler drain qilinadi. Faqat delay qo‘shish poygani yashiradi, proof emas. API dokumentatsiyasi borrow qilingan reference qaysi chaqiriqqacha yaroqli va caller uni saqlashi mumkinmi aniq ko‘rsatadi.
Bog‘liq tushunchalar
Dangling pointer, Memory safety, AddressSanitizer, Heap, RAII, Hazard pointer