بریم برای کالبدشکافی CVE-2025-68260. ماجرا از این قراره که یه فایل مشخص تو Binder کرنل لینوکس سالها با C وجود داشته. یه کد C قدیمی، حوصلهسربر، محافظهکارانه، ولی درست! لاکها شاید کمی طولانیتر بودن، ولی قانونش خیلی ساده و سفت و سخت بوده:
death_list همیشه زیر یه لاک واحد دستکاری میشد، مالکیتش هیچوقت مبهم نمیشد، و لیست از کنترل صاحبش خارج نمیشد. همین.
تا اینکه یه روز تصمیم گرفته میشه همین تیکه کد رو با فلسفهی «Rewrite it in Rust» بازنویسی کنن. نیت روی کاغذ خوبه:
لاک کوتاهتر، کد تمیزتر، استفاده از Rust تو سطح کرنل، و طبیعتاً یه دور افتخار و کلی بوق.تو پیادهسازی Rust، برای اینکه Borrow Checker راضی بشه و کد «Rusty» به نظر بیاد، تصمیم گرفته میشه که محتویات death_list رو موقتاً بکشن بیرون و بریزن تو یه لیست محلی، لاک رو رها کنن، بعد بیرون از لاک روش Iterate کنن.
روی کاغذ؟ عالی. لاک کوتاهتر شده.در عمل؟ یه قاعدهی همیشگی (Invariant) تاریخی Binder نابود شده.چیزی که تو نسخهی C اصلاً قابل تصور نبوده، نه بهخاطر امنیت C، بلکه بهخاطر «ذهنیت کرنلی» که میگفت لیست درونساختاری (Intrusive List) یا کاملاً مال لاکه، یا اصلاً وجود نداره. حد وسطی وجود نداشت. ولی تو نسخهی Rust، این Invariant تبدیل میشه به یه کامنت قشنگ بالای یه unsafe: «این نود یا تو همین لیسته یا هیچجا نیست.»
در حالی که دیگه درست نیست! نتیجه کاملاً قابل پیشبینیه: ایجاد Race Condition واقعی، دستکاری همزمان پوینترهای prev/next، فساد حافظه، کرش کرنل، و در نهایت یه CVE رسمی.
طنز تلخ ماجرا؟ همون فایل تو نسخهی C سالها بدون این داستانها کار کرده بوده. از نظر Performance هم داستان قشنگ نیست. نسخهی Rust اینجا نهتنها unsafe داره، بلکه Abstraction ،Indirection ،Refcounting و پیچیدگی هم اضافه کرده. یعنی هم سربار بیشتر، هم Reasoning سختتر. لاک کوتاهتر شده، ولی فهم کد سختتر شده! و تو کرنل این دقیقاً خلاف جهته.
مسئله اینه که Rust ابزار خوبیه، ولی وقتی یه کد کرنلی بالغ و Battle-tested رو بدون نیاز واقعی و بدون بازطراحی عمیق مدل همزمانی، صرفاً بازنویسی میکنی، احتمال اینکه بدترش کنی خیلی بالاست. مخصوصاً وقتی با Data Structureهای Intrusive و Invariantهای نانوشته سروکار داری.
از طرفی تو کرنل، کد Boring که سالها درست کار کرده، یه داراییه. بازنویسی فقط به این دلیل که «میشه با Rust نوشت»، فضیلت نیست! میتونه منبع Regression، پیچیدگی و باگ جدید باشه.
این قضیه برای ما تو دنیای امبدد یه زنگ خطر جدیتری هم داره. وقتی منابع محدودن و دیوایس قراره سالها تو فیلد بدون دسترسی فیزیکی کار کنه، «پیچیدگی» بزرگترین دشمنه. تو این سیستمها ما دنبال قطعیت (Determinis
m) و پیشبینیپذیری (Predictability) هستیم، نه Abstractionهایی که معلوم نیست اونزیر چه سرباری (Overhead) دارن.
اگه قراره Rust جایگزین C بشه، باید بتونه
همون سادگی و کارایی Bare-metal رو بده، نه اینکه برای حل مشکل مموری که خودش هم میتونه به بار بیاره، مشکل معماری درست کنه. تو امبدد، کدی که «شاید» Race داشته باشه ولی ۱۰ لایه رپ (Wrap) شده، خیلی ترسناکتر از کد C لُختیه که دقیق میدونی بیتبهبیتش داره چیکار میکنه.
برای جزییات بیشتر
اینجا رو بخونید.
📡
openpcb