Какво се крие зад принудителния недостатък на дизайна на Intel многобройни лепенки?

„КаквоIntel

И Windows, и Linux получават значителна сигурност актуализации, които в най-лошия случай могат да доведат до намаляване на ефективността половината, за да се защитим срещу проблем, който все още не е напълно разкрито.

Патчите към Linux ядрото се трупаха в миналото няколко седмици. Microsoft тества актуализациите на Windows в Инсайдерска програма от ноември и се очаква да бъде пусната промени в мейнстрийм Windows надгражда в Patch Вторник следващия седмица. Azure на Microsoft планира поддръжка през следващата седмица и AWS на Amazon е планирано за поддръжка в петък – вероятно свързани.

Откакто за първи път се появиха патчите на Linux, по-ясна картина от това, което изглежда не е наред. Докато Linux и Windows се различават в много отношения, основните елементи на това как тези две операционни системи – и наистина всяка друга операционна система x86 като FreeBSD и macOS – обработката на системната памет е същата, защото тези части на операционната система са толкова плътно свързани с възможностите на процесора.

Проследяване на адреси

Всеки байт памет в системата е имплицитно номериран, тези числата са адрес на всеки байт. Най-ранната експлоатация системи, работещи с физически адреси на паметта, но физически адресите на паметта са неудобни по много причини. Например, често има пропуски в адресите и (особено при 32-битови системи), физическите адреси могат да бъдат неудобни за манипулиране, изискващи 36-битови числа или дори по-големи.

Съответно, всички съвременни операционни системи зависят от широко концепция, наречена виртуална памет. Системите за виртуална памет позволяват и двете програми и самите ядра да работят в прост, чист, равномерна среда. Вместо физическите адреси с техните пропуски и други странности, използва всяка програма и самото ядро виртуални адреси за достъп до паметта. Тези виртуални адреси са непрекъснат – няма нужда да се притеснявате за пропуски – и е с удобен размер да ги направи лесни за манипулиране. 32-битовите програми виждат само 32-битови адреси, дори ако физическият адрес изисква 36-битов или повече номерация.

Въпреки че това виртуално адресиране е прозрачно за почти всеки софтуер, процесорът в крайна сметка трябва да знае кой физическа памет, към която се отнася виртуалният адрес. Има картографиране от виртуални адреси до физически адреси и това се съхранява в голяма структура от данни, наречена таблица на страниците. Операционните системи изграждат таблицата на страниците, използвайки оформление, определено от процесора, и процесор и операционна система заедно използват таблицата на страниците винаги, когато трябва да конвертират между виртуални и физически адреси.

Целият този процес на картографиране е толкова важен и основен модерни операционни системи и процесори, които процесорът има специален кеш – буферът за превод на външния вид или TLB – това съхранява определен брой виртуални към физически карти, така че да го може да избегнете използването на таблицата с пълна страница всеки път.

Използването на виртуална памет ни дава редица полезни функции отвъд простотата на адресиране. Главно сред тях е, че всеки индивидуална програма получава собствен набор от виртуални адреси, с собствен набор от виртуални към физически карти. Това е основна техника, използвана за осигуряване на “защитена памет”; един програма не може да се повреди или да се подправи паметта на друг програма, защото паметта на другата програма просто не е част от картографиране на първата програма.

Но тези употреби на индивидуално картографиране на процес и следователно допълнителни таблици за страници, оказва натиск върху TLB кеша. TLB не е много голям – обикновено няколкостотин карти – и повече таблици с страници, които системата използва, по-малко вероятно е TLB да включва всеки конкретен виртуален към физически превод.

Половината и половината

За да използвате най-добре TLB, всеки основен оператор система разделя обхвата на виртуалните адреси на два. Една половина от адресите се използват за всяка програма; другата половина се използва за ядрото. Когато превключвате между процеси, само половината страница записи в таблицата се променят – тези, които принадлежат на програмата. Ядрото половината е обща за всяка програма (тъй като има само едно ядро), и така тя може да използва едно и също картографиране на таблицата на страниците за всеки процес. Това помага на TLB изключително много; докато все още трябва да се изхвърли карти, принадлежащи към процеса на полза от адреси на паметта, тя може да запази съпоставянията за половината на ядрото.

Този дизайн не е напълно поставен в камък. Работата беше извършена Linux, за да може да се даде 32-битов процес на целия диапазон на адреси, без споделяне между таблицата на страницата на ядрото и тази на всяка програма. Докато това даваше на програмите повече адрес пространство, тя носеше разходи за изпълнение, защото TLB трябваше да се презареди таблицата на страницата на ядрото въвежда всеки път, когато кодът на ядрото е необходим се изпълнява. Съответно този подход никога не е бил широко използван на x86 системи.

Един недостатък на решението за разделяне на виртуалното адресно пространство между ядрото и всяка програма е, че защитата на паметта е отслабена. Ако ядрото има собствен набор от таблици за страници и виртуални адреси, ще бъде осигурена същата защита като различни програми имат една от друга; паметта на ядрото би бъдете просто невидими. Но с разделеното адресиране, потребителските програми и ядрото използва същия диапазон на адреси и по принцип a потребителската програма ще може да чете и записва ядрото на паметта.

За да се предотврати тази очевидно нежелана ситуация, процесорът и виртуалната система за адресиране имат концепция за „пръстени“ или „режими“. x86 процесорите имат много пръстени, но за този проблем са само два уместно: „потребител“ (пръстен 3) и „надзорник“ (пръстен 0). При бягане редовни потребителски програми, процесорът е поставен в потребителски режим, позвъняване 3. Когато работи код на ядрото, процесорът е в пръстен 0, надзор режим, известен още като режим на ядрото.

Тези пръстени се използват за защита на паметта на ядрото от потребителя програми. Таблиците на страниците не са просто картографиране от виртуална към физически адреси; те съдържат и метаданни за тях адреси, включително информация за това кои позвънявания могат да имат достъп до адрес. Всички записи в таблицата на страницата на ядрото са маркирани само като да е достъпен до звънене 0; записите в програмата са маркирани като да е достъпен от всеки пръстен. Ако се направи опит за достъп звъни 0 памет, докато е в пръстен 3, процесорът блокира достъпа и генерира изключение. Резултатът от това е, че потребителските програми, работи в ринг 3, не трябва да може да научи нищо за ядрото и паметта му на звънене 0.

Поне това е теорията. Пространството от корекции и актуализация покажете, че някъде това се е развалило. Тук е голямото мистерия лъжи.

Придвижване между пръстени

Ето какво знаем. Всеки модерен процесор изпълнява a определено количество спекулативно изпълнение. Например, като се има предвид някои инструкции, които добавят две числа и след това съхраняват резултата в памет, процесор може спекулативно да направи добавянето преди установяване дали местоназначението в паметта е всъщност достъпни и за записване. В общия случай, където е местоположението възможност за записване, процесорът успя да спести известно време, както го направи аритметично успоредно с измислянето на това, което в дестинацията памет беше. Ако установи, че местоположението не е достъпно – за например програма, която се опитва да запише на адрес, който няма картографиране и никакво физическо местоположение – тогава той ще генерира изключение и спекулативното изпълнение се пропилява.

Intel процесорите, по-специално – макар и да не са AMD – позволяват спекулативно изпълнение на ринг 3 код, който пише на звънене 0 памет. Процесорите правилно блокират записването, но спекулативното изпълнението мигновено нарушава състоянието на процесора, защото е сигурно данните ще бъдат заредени в кеш и TLB, за да се установи дали записът трябва да бъде разрешен. Това от своя страна означава, че някои операциите ще бъдат с няколко цикъла по-бързи или с няколко цикъла по-бавни, в зависимост от това дали техните данни все още са в кеш или не. Както и тъй като това, процесорите на Intel имат специални функции, като например Software Guard Extensions (SGX), въведени с процесори Skylake, което леко променя начина на обработка на опитите за достъп до паметта. Отново процесорът все още защитава паметта на звънене 0 от пръстен 3 програми, но отново са нейните кешове и други вътрешни състояния променени, създавайки измерими разлики.

Това, което все още не знаем, е само колко памет на ядрото информация може да изтече в потребителските програми или колко лесно това може да се появи изтичане. И кои процесори на Intel са засегнати? Отново не е напълно ясно, но индикациите са, че всеки чип на Intel с спекулативно изпълнение (което са всички основни процесори въведена след Pentium Pro, от 1995 г.) може да изтече информация насам.

Първият вятър на този проблем дойде от изследователи от Грац Технически университет в Австрия. Изтичането на информация те Откритият беше достатъчен, за да подкопае режима на ядрото Разположение на адреса Рандомизация (ASLR на ядрото или KASLR). ASLR е нещо като последно усилие за предотвратяване на експлоатацията на буферните преливания. С ASLR програмите и техните данни се поставят в произволна памет адреси, което прави малко по-трудно експлоатацията на нападателите пропуски в сигурността. KASLR прилага същата тази рандомизация към ядрото така че данните на ядрото (включително таблиците на страниците) са и кодът разположен на случаен принцип.

Изследователите в Грац разработиха KAISER, набор от Linux ядро пачове за защита срещу проблема.

Ако проблемът беше само, че той даде възможност за дерандомизация на ASLR, това вероятно не би било голямо бедствие. ASLR е хубаво защита, но се знае, че е несъвършен. Това е предназначено да бъде a препятствие за нападателите, а не непроницаема бариера. Индустрията реакция – разработена доста голяма промяна както за Windows, така и за Linux с известна секретност – предполага, че не само ASLR е победен и че по-обща способност за изтичане на информация от ядрото е разработен. Всъщност изследователите са започнали да туитрат това те могат да текат и четат произволни данни на ядрото. още Възможността е недостатъкът да се използва за бягство от виртуална машина и компрометира хипервизор.

Решението, което имат както разработчиците на Windows, така и Linux избраната е по същество еднаква и произлиза от тази KAISER работа: записите в таблицата на страницата на ядрото вече не се споделят с всеки процес. В Linux това се нарича Kernel Page Table Isolation (KPTI).

С кръпките, адресът на паметта все още е разделен на две; е просто половината на ядрото е почти празна. Не е съвсем празно, защото няколко парчета ядро ​​трябва да бъдат картографирани постоянно, независимо дали процесор работи в пръстен 3 или пръстен 0, но е близо до празно. Това означава, че дори и злонамерена потребителска програма да се опита да проучи паметта на ядрото и информацията за изтичане, тя ще се провали – има просто нищо да не изтече. Реалните таблици на страниците на ядрото се използват само когато самото ядро ​​работи.

Това подкопава самата причина за разделеното адресно пространство в първо място. Сега TLB трябва да изчисти всички записи, свързани към таблиците на страниците на истинските ядра всеки път, когато премине към потребител програма, слагайки край на ефективността, спестявайки това разделяне активирана.

Въздействието на това ще варира в зависимост от натовареността. всеки време, когато програма направи повикване в ядрото – да чете от диск, до изпращайте данни в мрежата, за да отворите файл и т.н. – това обаждане ще бъдете малко по-скъпи, тъй като това ще принуди TLB да бъде изчерпайте и истинската таблица на страницата на ядрото, която трябва да се зареди. Програми, които не използвайте ядрото, може би ще видите хит от 2-3 процент – все още има някои режийни разходи, защото ядрото винаги има да тичам от време на време, да се справяш с неща като многозадачност.

Но натоварванията, които извикват в ядрото тон, ще видят много по-голямо отпадане на производителността В еталон, програма, която прави почти нищо друго освен извикване в ядрото не видя спад на производителността с около 50 процента; с други думи, всяко обаждане в ядрото отне два пъти по-дълго с пластира, отколкото го направи без. Бенчмарки, които използват мрежата за връщане към Linux, също вижте a голям хит, като например 17 процента в този показател за Postgres. реален натовареността на базата данни, използваща реална мрежа, трябва да види по-малко въздействие, защото с реалните мрежи, разходите за извикване в ядрото обикновено е доминиран от режийните разходи за използване на действителните мрежа.

Докато системите на Intel са тези, за които се знае, че имат дефекта, те може да не са единствените засегнати. Някои платформи, като SPARC и S390 на IBM, са имунизирани срещу проблема като техния процесор управлението на паметта не се нуждае от разделено адресно пространство и споделено таблици със страници на ядрото; операционни системи на тези платформи имат винаги са изолирали техните таблици на страницата на ядрото от тези в потребителския режим. Но други, като ARM, може да нямат толкова късмет; сравними пластири за ARM Linux се разработва.

Like this post? Please share to your friends:
Leave a Reply

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: