Reptar: Intel CPU में FSRM/REX भेद्यता
(lock.cmpxchg8b.com)- कुछ Intel प्रोसेसरों में जब
rep movsऔर डुप्लिकेटrex.rप्रीफिक्स FSRM optimization के साथ मिलते हैं, तो CPU सामान्य नियमों से बाहर एक “glitch” स्थिति में जा सकता है - इसका कारण x86 की ढीली prefix decoding और
movsbजैसे implicit operands इस्तेमाल करने वाले निर्देशों में ऐसाrexप्रीफिक्स है, जो सामान्यतः निरर्थक होना चाहिए, लेकिन एक खास optimization path को ट्रिगर कर देता है - Google की verification pipeline ने अगस्त 2023 में इस संयोजन में अप्रत्याशित परिणाम पाए, और unexpected branch, unconditional branch को अनदेखा करना, तथा
xsaveऔरcallमें instruction pointer रिकॉर्डिंग की गड़बड़ी देखी - अगर कई कोर एक साथ यही बग ट्रिगर करें, तो machine check exception और सिस्टम halt हो सकता है; यह unprivileged guest VM के भीतर भी reproduce होता है, इसलिए cloud environments के लिए महत्वपूर्ण है
- Intel ने प्रभावित प्रोसेसरों के लिए microcode update जारी किया है; अगर update संभव न हो, तो
IA32_MISC_ENABLEमें fast strings को disable किया जा सकता है, लेकिन इससे performance में बड़ा गिरावट आता है
x86 प्रीफिक्स और rep movsb
rep movsbx86 में memory कॉपी करने का एक प्रचलित तरीका है, जिसमें source, destination, direction और count सेट करने पर प्रोसेसर बार-बार copy को संभालता है- असली instruction
movsbहै, औरrepएक prefix है जो उस instruction को कई बार दोहराने के लिए बदल देता है - x86 instruction decoding अपेक्षाकृत ढीली है, इसलिए अर्थहीन या टकराने वाले प्रीफिक्स लगे होने पर भी उन्हें अक्सर अनदेखा कर दिया जाता है
- compiler ऐसे डुप्लिकेट प्रीफिक्स का उपयोग एक single instruction को इच्छित alignment boundary तक padding देने के लिए कर सकता है
rex,vex,evexऐसे प्रीफिक्स हैं जो बाद के instruction के decode होने का तरीका बदलते हैं
rex प्रीफिक्स का समस्याग्रस्त संयोजन
- i386 में general-purpose registers 8 थे, इसलिए 3 बिट से register चुना जा सकता था, लेकिन x86-64 में general-purpose registers 16 हैं, इसलिए अतिरिक्त बिट की जरूरत पड़ती है
rexप्रीफिक्स अगले instruction को operands encode करते समय इस्तेमाल के लिए अतिरिक्त बिट देता है- इसे आमतौर पर
rex.rxbकी तरह लिखा जाता है, जहाँb,x,r,wबिट वैकल्पिक रूप से सेट होते हैं
- इसे आमतौर पर
movsbमें operands instruction में स्पष्ट रूप से लिखे नहीं जाते और सभी implicit होते हैं, इसलिएrex.rxb rep movsbमेंrexबिटों का कोई अर्थ नहीं होना चाहिए- सामान्यतः प्रोसेसर ऐसे
rexप्रीफिक्स को चुपचाप अनदेखा करता है, लेकिन fast short repeat move सपोर्ट करने वाले सिस्टमों में यही संयोजन भेद्यता बन जाता है
FSRM और प्रभावित प्रोसेसर
- FSRM Ice Lake में लाया गया फीचर है, जो ERMS की short string handling सीमाओं को पूरा करता है
- ERMS (enhanced repeat move/store) buffer alignment और wide stores को microcode में संभालकर मौजूदा
rep movsbcode को तेज बना सकता है- इसका शुरुआती setup cost बड़ा होता है, इसलिए बहुत छोटी strings के लिए यह उपयुक्त नहीं है
- FSRM 128 bytes या उससे कम के छोटे move को तेज़ी से संभालने के लिए बना है
/proc/cpuinfoकीflagsलाइन मेंfsrmफ्लैग देखकर सपोर्ट जाँचा जा सकता है- FSRM वाले प्रोसेसरों के उदाहरण:
- Ice Lake
- Rocket Lake
- Tiger Lake
- Raptor Lake
- Alder Lake
- Sapphire Rapids
- यह सूची पूर्ण नहीं है; पूरी सूची के लिए Intel advisory INTEL-SA-00950 देखना चाहिए
खोज और पुनरुत्पादन
- Google की verification pipeline Oracle Serialization तकनीक से random generated programs के दो रूप चलाकर यह तुलना करती है कि final state एक जैसी है या नहीं
- संबंधित विवरण पहले के लेख Oracle Serialization में है
- अगस्त 2023 में FSRM-optimized
rep movsमें डुप्लिकेटrex.rप्रीफिक्स जोड़ने पर अप्रत्याशित परिणाम देखे गए - देखे गए असामान्य व्यवहार:
- अप्रत्याशित स्थान पर branch होना
- unconditional branch को अनदेखा करना
xsaveयाcallinstruction में instruction pointer सही तरह रिकॉर्ड न होना- debugger द्वारा असंभव स्थिति की रिपोर्ट करना
- जब कई कोर यही बग ट्रिगर करते हैं, तो प्रोसेसर machine check exception रिपोर्ट कर सकता है और रुक सकता है
- यह unprivileged guest VM के भीतर भी reproduce हो सकता है, जिससे cloud providers के लिए यह एक महत्वपूर्ण सुरक्षा मुद्दा बनता है
- reproduction tools और research materials Google के security research repository में उपलब्ध हैं
icebreakटूल का local mirror भी icebreak.tar.gz के रूप में दिया गया है
icebreakअलग-अलग core pairs चुनकर reproduction की कोशिश करता है- अप्रभावित सिस्टमों में यह infinite loop जैसा दिखना चाहिए और कोई output नहीं आना चाहिए
- प्रभावित सिस्टमों में हर सफल reproduction पर
.आउटपुट होगा - SMT sibling cores पर arbitrary branch देखी जा सकती है
- एक ही package के SMP sibling cores पर machine check देखा जा सकता है
- यदि दो अलग कोर नहीं चुने गए, तो hammer thread की जरूरत पड़ सकती है
संभावित कारण और देखे गए प्रभाव
- आधुनिक सिस्टमों का microcode व्यवहार सार्वजनिक नहीं है, इसलिए मूल कारण पर केवल अवलोकन-आधारित सिद्धांत ही दिए जा सकते हैं
- CPU को मोटे तौर पर frontend और backend में बाँटा जा सकता है
- frontend instructions को fetch और decode करके μops बनाता है
- backend instructions को out-of-order चलाता है, ROB (reorder buffer) में परिणाम रखता है और retire करता है
- ऐसा लगता है कि यह बग frontend को
movsbinstruction का आकार गलत गिनने पर मजबूर करता है, जिससे बाद की ROB entries गलत address से जुड़ जाती हैं - इस स्थिति में instruction pointer की गलत गणना के साथ एक भ्रमित स्थिति पैदा होती है
- सिस्टम अंततः अंदरूनी रूप से फिर से consistent state में लौट सकता है, लेकिन बीच के परिणाम गलत हो सकते हैं
- अगर कई SMT या SMP कोर एक साथ इस स्थिति में जाएँ, तो microarchitectural state को इतना नुकसान हो सकता है कि machine check मजबूर हो जाए
- सिस्टम state को इतना नुकसान पहुँचाया जा सकता है कि machine check हो जाए, और SMT sibling cores पर schedule की गई processes के execution में thread-to-thread interference भी देखा गया
- यह पुष्टि नहीं हुई है कि इस corruption को इतना सटीक नियंत्रित किया जा सकता है कि privilege escalation संभव हो सके
समाधान के तरीके
- Intel ने सभी प्रभावित प्रोसेसरों के लिए अपडेटेड microcode INTEL-SA-00950 के रूप में जारी किया है
- हो सकता है operating system या BIOS vendor पहले से update उपलब्ध करा रहे हों
- अगर update नहीं किया जा सकता, तो
IA32_MISC_ENABLEmodel-specific register के जरिए fast strings disable किए जा सकते हैं - fast strings disable करने से performance में बड़ी गिरावट आती है, इसलिए इसे केवल बिल्कुल आवश्यक होने पर ही उपयोग करना चाहिए
संबंधित CPU बग संसाधन
- Google अपने खोजे गए CPU बग सार्वजनिक करता रहा है, और उनमें से कुछ सुरक्षा प्रभाव न होने पर भी पढ़ने लायक हैं
- उदाहरण संसाधन
- movlps just doesn’t work:
movlpsके काम न करने का मामला - registers can sometimes roll back: registers के पहले के मान पर लौट जाने का मामला
- movlps just doesn’t work:
1 टिप्पणियां
Hacker News की राय
संबंधित लेख: https://cloud.google.com/blog/products/identity-security/goo...
यह https://news.ycombinator.com/item?id=38268043 से आया था, लेकिन टिप्पणियां यहां मर्ज कर दी गईं
यह लेख पढ़कर एहसास हुआ कि मेरा software जिस hardware पर चलता है, उसके बारे में मुझे कितना कम पता है
इसमें कहा गया है कि “prefix किसी feature को on या off करके instruction के व्यवहार को बदलने देता है”, तो सोच रहा हूं कि किसी feature को on/off करने के लिए “prefix” की जरूरत क्यों पड़ती है
क्या इसका मकसद BIOS में जाए बिना features को dynamically switch करना है?
REP prefix सबसे आम है; इसका काम वही instruction variable संख्या में बार-बार दोहराना है
दोहराव की संख्या CX register से ली जाती है, और यह memory से objects move करने जैसे आम loops को बहुत छोटा बना देता है
memcpy function अक्सर REP MOVS नाम की एक instruction के रूप में inline किया जाता है, और जरूरत हो तो count को CX में copy करने वाली instruction साथ जुड़ती है
REX prefix भी काफी आम है, क्योंकि 64-bit programs अक्सर 64-bit values और addresses से निपटते हैं
कोई भी prefix BIOS आदि से globally configurable किसी चीज़ को toggle नहीं करता; वे सभी सिर्फ यह बताते हैं कि अगली instruction को क्या करना है
कम इस्तेमाल होने वाले addressing modes में “segment prefix” लगता है, जो DS के बजाय कोई दूसरा segment इस्तेमाल करवाता है, और x86_64 का “REX” prefix register field में bits जोड़ता है, जिससे 16 general-purpose registers इस्तेमाल किए जा सके
इसी तरह “LOCK” prefix, भले ही उसका मूल specification खराब था, कुछ memory operations को बाकी system के संदर्भ में atomic बनाता है, जैसे “LOCK CMPXCHG” से compare-and-set लागू करना
दूसरी CPU architectures भी ऐसे operations को व्यक्त करती हैं, लेकिन आम तौर पर उन्हें मौजूदा instruction space के भीतर डालती हैं, जिससे सभी instructions को व्यक्त करने के लिए अधिक bits चाहिए होते हैं
यहां खास तौर पर समस्या बना “REP” prefix एक अपवाद जैसा है; यह प्राचीन समय से बचा हुआ microcode repetition prefix है
फिर भी यह memset/memmove जैसे आज भी performance-sensitive operations को दर्शाता है, इसलिए CPU vendors के लिए इसे optimize करते रहना सार्थक है, और लगता है यह bug उसी प्रक्रिया में पैदा हुआ
सबसे बड़ी समस्या यह है कि instruction encoding space का “कुशलता से इस्तेमाल” किया गया था
बाद में जब नई instructions, और उससे भी खराब, अतिरिक्त registers आए, तो नए instruction variants को किसी तरह फिट करना पड़ा, और तरीका था prefixes जोड़ देना
हर बार instruction set बढ़ाते समय opcode space का कुछ हिस्सा खोदकर नया prefix ठूंस दिया गया
Intel ने इस साल एक और नया तरीका प्रस्तावित किया है, इसे देखते हुए लगता है यह प्रवृत्ति जारी रहेगी
diagnosis process देखकर qemu के repz ret से टकराने पर हुई बात याद आ गई: https://repzret.org/p/repzret/
HN rules के हिसाब से ऐसे titles पर रोक होनी चाहिए, ऐसा मुझे लगता है
इससे link किस बारे में है, बिल्कुल पता नहीं चलता, और URL तो उल्टा और confuse करता है
इतना अर्थहीन title हो तो poster को एक छोटा explanation जोड़ना चाहिए, ऐसा मुझे लगता है
मैंने देखा है कि जब title में ज्यादा से ज्यादा context दे दिया जाता है, तो लोग link click नहीं करते और tweet पर react करने की तरह comments में सिर्फ अपनी दिलचस्पियों को तराशने लगते हैं
HN intellectual curiosity और link click कराने के बीच का रास्ता चुनता है
title अस्पष्ट होने की वजह से अगर आप link click करने से इनकार भी करें, तो कम से कम जवाब उन लोगों को देंगे जिन्होंने link click किया है, इसलिए यह internet की बाकी जगहों से बेहतर है
जिन posts में अस्पष्ट और चतुर title को justify करने लायक reward नहीं होता, वे इस post के विपरीत front page से उतर जाती हैं
लेख बहुत अच्छी तरह लिखा गया है
assembly programming और Intel instruction set, यहां तक कि microarchitecture के बारे में भी मैं लगभग कुछ नहीं जानता, फिर भी explanation follow कर सका और लगा कि यहां क्या हो रहा है, उसका मोटा-मोटा अंदाजा हो गया
क्या किसी को पता है कि AMD CPU भी प्रभावित हैं या नहीं?
अगर समस्या सचमुच यह है कि processor instruction length को लेकर confuse हो रहा है, तो यह प्रभावशाली है कि इसे microcode से बिना बड़ी performance drop के ठीक किया जा सकता है
मेरी intuition पूरी तरह गलत हो सकती है, लेकिन मुझे लगा था कि instruction length calculation सीधे logic gates से synthesize होती होगी
फिर सोचा तो हो सकता है कि uOP decoder hardware के स्तर पर ठीक हो, और microcode में optimized copy routine uOP stream के बारे में कोई ऐसी बात infer करने की कोशिश कर रही हो जो सच नहीं है
जैसे “अरे, यह rep mov है, तो loop के लिए दो uOP पीछे जाना ठीक रहेगा” जैसा कुछ
Intel CPU team शायद details तक public नहीं करेगी
“ERMS” और “FSRM” के बारे में मुझे ठीक से नहीं पता, और Google पर भी अच्छे resources बहुत कम दिखते हैं
मुझे यह जानना है कि क्या ये सिर्फ CPUID flags हैं जो बताते हैं कि
rep movsbको optimized SSEmemcpyimplementation की जगह top performance के लिए इस्तेमाल किया जा सकता है, या फिर येrep movsbको तेज़ बनाने वाली कोई खास encoding या prefix हैंअगर दूसरा मामला है, तो यह क्यों ज़रूरी है और fsrm का इस्तेमाल कैसे होता है, यह भी समझ नहीं आ रहा
लगता है ERMS, AVX का सस्ता विकल्प था, और FSRM छोटे blocks के लिए बेहतर version था
“बाद के processors के low-end versions, यानी 2017 में जारी Kaby Lake Celeron और Pentium में तेज़ memory copy के लिए इस्तेमाल हो सकने वाला AVX नहीं है, लेकिन Enhanced REP MOVSB है
और 2018 के बाद जारी कुछ Intel mobile और low-power architectures SkyLake आधारित नहीं थे, फिर भी वे पिछली पीढ़ी की microarchitecture की तुलना में REP MOVSB से प्रति CPU cycle लगभग दोगुने bytes copy करते हैं”
“Ice Lake microarchitecture के Fast Short REP MOV(FSRM) से पहले Enhanced REP MOVSB(ERMSB), block size कम-से-कम 256 bytes होने पर ही AVX copy या general-purpose register copy से तेज़ था
64 bytes से छोटे blocks में ERMSB की internal startup cost लगभग 35 cycles ज्यादा थी, इसलिए वह काफी धीमा था, और FSRM feature का मकसद 128 bytes से छोटे blocks को भी तेज़ करना था”
[1] https://stackoverflow.com/a/43837564
[2] http://www.intel.com/content/dam/www/public/us/en/documents/...
बेहतर instruction selection और scheduling compile time पर statically भी किया जा सकता है, या runtime पर कई library functions में से एक चुनकर या JIT के जरिए dynamically भी
runtime पर कौन-सी instruction scheduling optimal है, यह detect करने के लिए actual CPU जानना पड़ता है
सभी CPU models की table रखी जा सकती है, लेकिन OS से यह भी पूछा जा सकता है कि चल रहा CPU वह optimization implement करता है या नहीं
Linux को patch की ज़रूरत थी ताकि CPU यह report कर सके कि उसने वह optimization implement किया है
https://www.phoronix.com/news/Intel-5.6-FSRM-Memmove
मैंने Intel advisory [1] में यह लिखा देखा
Intel ने कहा कि वह इस issue को internally खोजने वाले Intel कर्मचारियों का धन्यवाद करता है, और इस issue की report करने वाले Google कर्मचारियों का भी धन्यवाद करता है
[1] https://www.intel.com/content/www/us/en/security-center/advi...
impact description वाली Intel advisory भी देखने लायक है: https://www.intel.com/content/www/us/en/security-center/advi...
“कुछ Intel(R) processors में processor instruction sequence अनपेक्षित behavior पैदा कर सकता है, जिससे authenticated user local access के जरिए privilege escalation, information disclosure, या denial of service संभव कर सकता है”
Paradox Interactive की Victoria 3 team के Konrad Magnusson ने इससे और mimalloc से जुड़ी कोई चीज़ पाई: https://github.com/microsoft/mimalloc/issues/807
पता नहीं यह पूरी तरह related है या नहीं, लेकिन संभावना है