16. سپتامبر 2026
باگ سهساله از دست رفتن بیصدا داده روی x86 بعد از MADV_FREE بسته شد

۲ سپتامبر ۲۰۲۶ Orson Peters از تیم Polars یک reproducer کوتاه به linux-mm فرستاد: بافر را پر کن، madvise(MADV_FREE) بزن، دوباره بنویس، زیر فشار memcg نوشتهٔ دوم ناپدید میشود. خواندن بعدی صفحهٔ صفر برمیگرداند. هیچ errno، هیچ SIGBUS. گزارش میگوید کاربران Polars در production داده از دست دادهاند — ترکیب درست hugepage، MADV_FREE و reclaim سنگین.
Phoronix ۱۴ سپتامبر (حدود ۶:۱۳ صبح EDT) نوشت پچ بعد از Linux 7.3-rc3 برای باگ از دست رفتن بیصدای user-space که سه سال در کرنل بوده merge شده است. permalink دقیق مقاله را از اسلاگهای رایج نتوانستیم باز کنیم؛ خودِ پچ و tip tree منبع قطعیاند.
یک بیت که از کار shadow-stack جا مانده بود
Vernon Yang علت را ظرف یک روز پیدا کرد. از لینوکس ۶٫۶، در مسیر آمادهسازی shadow-stack روی x86، pmd_modify() مقدار PMD را با (_HPAGE_CHG_MASK & ~_PAGE_DIRTY) ماسک میکرد و بیت dirty سختافزار را دور میریخت. pmd_mksaveddirty() قرار بود _PAGE_DIRTY را به _PAGE_SAVED_DIRTY منتقل کند، ولی چیزی برای انتقال نمانده بود. pte_modify() و pud_modify() این بیت را نگه میداشتند؛ PMD استثنا بود.
سناریوی قابلمشاهده روی THP نگاشتشده با PMD:
- memset؛ PMD dirty است
MADV_FREE— PMD پاک میشود ولی writable میماند، folio lazyfree- memset دوباره — سختافزار
_PAGE_DIRTYرا برمیگرداند mprotectفقطخواندنی (یا NUMA hinting) ازpmd_modify()میگذرد و بیت را میکشد- reclaim، مثلاً زیر سقف cgroup، folio را در
__discard_anon_folio_pmd_locked()آزاد میکند - fault بعدی صفحهٔ صفر تازه میآورد
NUMA balancing بهتنهایی، از مسیر do_huge_pmd_numa_page()، همان ضرر را میزند. THP فایلی هم میتواند writeback را از دست بدهد.
پچ یک خط است؛ تا رسیدن stable، THP را ببندید
در arch/x86/include/asm/pgtable.h ماسک به _HPAGE_CHG_MASK برگشته — _PAGE_DIRTY دیگر عمداً حذف نمیشود. پچ و ورود به tip: x86/urgent با عنوان «Fix user-space data loss with MADV_FREE and THP». Fixes روی bb3aadf7d446 («Start actually marking _PAGE_SAVED_DIRTY»). Reviewed-by از Rick Edgecombe که سری اصلی shadow-stack را نوشته. Cc: stable@xxxxxxxxxxxxxxx. Techveda میگوید یک مهندس SUSE مورد مشتری جدا هم با همین پچ بسته؛ merge به mainline بعد از 7.3-rc3.
arm64 درگیر نیست. هر x86 از ۶٫۶ تا RCهای ۷٫۳ درگیر است. allocatorهای مدرن خودشان MADV_FREE میزنند؛ سقف حافظهٔ systemd و کانتینر هم معمولی است. تا نقطهٔ پایدار شاخهتان پچ را بگیرد، transparent_hugepage=never ماشه را برمیدارد — با هزینهٔ عملکرد. کل point release را بردارید، نه cherry-pick تکخط.