LINUX.ORG.RU

В процессорах Loongson для Linux-систем обнаружили аппаратную утечку данных из L1-кеша

 , ,

В процессорах Loongson для Linux-систем обнаружили аппаратную утечку данных из L1-кеша

2

1

Исследователи из немецкого Центра информационной безопасности имени Гельмгольца CISPA представили на конференции USENIX Security 2026 аппаратную уязвимость LoongLeak, обнаруженную в китайских процессорах Loongson 3A5000 и Loongson 3A6000. Непривилегированная программа может использовать её для извлечения оставшихся в кеше первого уровня данных других процессов, ядра операционной системы и гипервизора. Атака также возможна из контейнера или гостевой виртуальной машины.

Практическое значение уязвимости связано прежде всего с Linux и другим свободным ПО. Для LoongArch существует отдельный порт в основном ядре Linux, а Debian уже включил loong64 в число официальных архитектур с планом выпуска в составе Debian 14. Поддержку архитектуры также развивают другие Linux-дистрибутивы и проекты открытого системного ПО.

Официальной версии Windows для LoongArch при этом нет. В перечнях поддерживаемых Microsoft процессоров для Windows 11 фигурируют решения AMD, Intel и Qualcomm, а установочные образы операционной системы выпускаются отдельно для x64 (microsoft.com) и Arm64. Поэтому компьютеры и серверы на Loongson на практике ориентированы прежде всего на Linux и открытый программный стек. Сама LoongArch, однако, является собственной архитектурой Loongson, поэтому речь идёт именно об открытости используемых операционных систем и программного окружения, а не о полной открытости процессора по модели RISC-V.

LoongLeak связана с особенностями выполнения инструкции FLD.S. В соответствии с руководством по архитектуре LoongArch она загружает из памяти 32-разрядное значение в 64-разрядный регистр с плавающей точкой, оставляя его старшие 32 бита в «неопределённом» состоянии. При использовании 256-разрядного векторного расширения LASX неопределёнными оказываются уже 224 бита, или 28 байт.

Исследователи установили, что в этих разрядах могут появляться не случайные значения, а данные, оставшиеся после предыдущих операций в кеше L1D. Атакующий способен подготовить внутреннее состояние процессора и выбирать нужный набор кеша, смещение внутри кеш-линии и один из её путей. Полученная информация непосредственно попадает в архитектурно доступные регистры.

Этим LoongLeak отличается от Spectre, Meltdown и большинства классических атак по сторонним каналам. Для извлечения информации не требуются спекулятивное выполнение, высокоточный таймер или анализ задержек обращения к памяти. Авторы работы классифицируют LoongLeak как архитектурную ошибку: процессор возвращает посторонние данные в результате штатного выполнения инструкции.

В лабораторных условиях средняя скорость извлечения информации достигла 315,8 Мбайт/с, а необработанный поток данных — 483,3 Мбайт/с. В более реалистичных сценариях, требующих переключения процессов или виртуальных машин, скорость снизилась до 6,2 и 4,5 Мбайт/с соответственно. Для проведения атаки злоумышленнику необходимо запустить непривилегированный нативный код на уязвимой системе, причём атакующий и жертва должны последовательно или одновременно выполняться на одном физическом ядре.

Для демонстрации последствий исследователи извлекли из памяти ядра Linux полный 512-разрядный мастер-ключ тома, зашифрованного при помощи LUKS и AES-XTS. В другом эксперименте с Loongson 3A6000 через общий для двух SMT-потоков кеш удалось получить первые 32 байта записи пользователя root из /etc/shadow, включая полную соль и девять байт хеша пароля.

LoongLeak также позволила получить значения ASLR и stack canary, используемые для усложнения эксплуатации ошибок памяти. Кроме того, исследователи продемонстрировали возможность пересечения границ виртуализации: код внутри гостевой системы способен извлекать данные другой виртуальной машины или самого гипервизора. Это делает проблему особенно существенной для многопользовательских серверов, облачных платформ и систем виртуализации на базе Linux и KVM.

Полностью исправить уязвимые процессоры обновлением Linux, микрокода или другого программного обеспечения нельзя, поскольку первопричина находится в аппаратной реализации. В качестве временной защиты предлагается вытеснять содержимое L1D-кеша несекретными данными при переходе из ядра в пользовательское пространство. В тестах исследователей максимальное замедление от такой меры составило 1,4%, а в большинстве тестов падение производительности не превышало 0,1%.

На Loongson 3A6000 дополнительно необходимо отключить один логический поток каждого физического ядра, фактически отказавшись от SMT. Другой вариант — перехватывать и программно эмулировать инструкции с плавающей точкой, LSX и LASX, однако в тестах с интенсивным использованием плавающей арифметики это приводило к замедлению в 10–21 раз.

Исследователи сообщили Loongson об уязвимости 23 июля 2025 года. Компания воспроизвела проблему и попросила сохранить сведения о ней в тайне на один год. Впоследствии производитель устранил утечку в новой аппаратной ревизии Loongson 3A6000. Владельцам ранее выпущенных 3A5000 и 3A6000 остаётся использовать программные меры снижения риска либо заменить процессор. Специальных средств, позволяющих обнаружить уже проводившуюся атаку LoongLeak, пока нет.

>>> Источник

★★★★★

Проверено: cetjs2 ()
Последнее исправление: cetjs2 (всего исправлений: 1)

я же говорил, что ни за 5, ни за 6 тысяч ничего нормального не сделают

unclestephen ★★★★★
() автор топика

в китайских процессорах Loongson 3A5000 и Loongson 3A6000

кто бы сомневался

dynamic_cast
()

LoongLeak связана с особенностями выполнения инструкции FLD.S. В соответствии с руководством по архитектуре LoongArch она загружает из памяти 32-разрядное значение в 64-разрядный регистр с плавающей точкой, оставляя его старшие 32 бита в «неопределённом» состоянии.

Ну понятно. Типичная детская ошибка неустоявшейся архитектуры. Исправят через пару релизов.

VIT ★★★
()

Прямо uninitialized kernel memory read, только в проце.

А автору новости, нейрослоперу unclestephen, в очередной раз шлю осуждение за помойный стиль изложения.

firkax ★★★★★
()
Ответ на: комментарий от firkax

В железе? Там нужно инициализировать нетронутые участки, причём в инструкциях всех размеров. Cофтом это не сделать.

VIT ★★★
()
Ответ на: комментарий от VIT

интересно, а старое можно будет вернуть по гарантии

а то как в анекдоте про исправление ошибки в swap файле

unclestephen ★★★★★
() автор топика
Ответ на: комментарий от unclestephen

Если внимательно подумать, опасность этой ошибки сильно зависит от способа применения узла. Конечно, в многопользовательской системе утечка данных опасна, тем более что есть эксплойт. В однопользовательской системе, например в ИИ-обучалке или вычислительном кластере ошибка неважна. Поэтому реакция должна быть индивидуальна на местах.

Ситуация обычная и рядовая. Даже в установившихся узлах одна-две ошибки на кремний бывают постоянно.

VIT ★★★
()
Ответ на: комментарий от VIT

...полугосударственное производство...

Это как?

sparkie ★★★★★
()
Ответ на: комментарий от sparkie

Смешанный капитал. В Китае часто финансирование разделяется между государством и местным управлением. Местные продают контракты частникам.

VIT ★★★
()

У меня, как у разработчика процессора, возникает целая гамма вопросов по этому поводу.

LoongLeak связана с особенностями выполнения инструкции FLD.S. В соответствии с руководством по архитектуре LoongArch она загружает из памяти 32-разрядное значение в 64-разрядный регистр с плавающей точкой, оставляя его старшие 32 бита в «неопределённом» состоянии. При использовании 256-разрядного векторного расширения LASX неопределёнными оказываются уже 224 бита, или 28 байт.

Это я могу понять. Утекло содержимое например другого регистра при переименовании. Что кстати тоже очень долбучий баг, но контроллируемый. Но тут:

В качестве временной защиты предлагается вытеснять содержимое L1D-кеша несекретными данными при переходе из ядра в пользовательское пространство.

Чевооо? Вот тут я реально удивился. Почему точно такого же бага нет на обычной загрузке 32битных целых чисел? Не, я в курсе что там верхняя часть приходит с прошлого регистра, но почему точно такое же поведение не заюзали в плавающих регистрах? Ладно, допустим что как я выше писал, обосрались. Тогда должны были появиться данные из какого-то регистра, который «при жизни» был в этом физическом регистре. Но поступили данные из кэша.

Окей. Допустим. Допустим в моем процессоре я обосрался и допустил такую же дикую запись 32х байт вместо 4х. Как работает команда чтения? Она читает регистры, складывает адрес со смещением, помещает их в блок TLB где выносится решение, дальше там уже мои хитрости с демпферированием потока команд в кэш. Но на этапе TLB произошел бы отбой запроса, команда бы пошла на исполнение с признаком не делать ничего, а лишь при запуске подвисшей команды чтения поставить признак сбоя. То есть снова ничего ужасного бы не было.

Почему оно читает L1-кэш в обход MMU?

Ведь это означает что там meltdown или его аналог в полный рост.

ckotctvo
()
Ответ на: комментарий от ckotctvo

Ты как-то всё усложняешь.

В кеш из памяти читаются 32 бита (или ничего не читается если они уже есть в кеше). Затем в регистр из кеша переносится столько битов сколько нужно для регистра.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

я пытаюсь восстановить последовательность операций которые процессор делает.

есть вариант x86 с PIPT-кэшем - у меня также.

есть вариант ARM с VIPT-кэшем - но у арма-то не течет. так другой секс бывает и поэтому я отказался от. по сути это отложенное на 1 такт сравнение части тэгов.

это ведь «стандартные решения» = делай как все, будет как у всех. В случае логсуна мы видим что-то очень сильно нехорошее: протекает MMU.

ckotctvo
()
Ответ на: комментарий от firkax

ложняешь.В кеш из памяти читаются 32 бита (или ничего не читается если они уже есть в кеше). Затем в регистр из кеша переносится столько битов сколько нужн

кэш так не работает. там всегда обмен идет линейками - по 64 байта например.

ckotctvo
()
Ответ на: комментарий от ckotctvo

Я ж написал эту последовательность: читаем 32 бита в кеш, читаем 64 бита из кеша в регистр. Чего тебе не хватает то?

кэш так не работает. там всегда обмен идет линейками - по 64 байта например.

А что будут если эти 4 байта настоящего чтения расположены в байтах 60..63 линейки, откуда возьмутся оставшиеся 4? Из соседней?

Ладно, я посмотрел pdf, там логика немного другая, но она даёт даже больше возможностей.

Сначала одной инструкцией проц провоцируется на чтение нужных секретных данных в какой-то блок кеша, без предоставления к ним доступа к ним на чтение из непривилегированного кода (инструкция XVLD, не знаю что она должна делать). Затем этой самой FLD.S читаются 4 байта откуда-то из памяти, и так вот, если тут происодит попадание в кеш и данные из памяти читать не надо, то 8 байт читаются из кеша нужной линии, а остальные 8..31 - из той что была в предыдущей операции.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

Хотя XVLD это кажется 32-байтное чтение, не понял тогда как они провоцируют загрузку именно секретных данных в кеш. Можешь сайт посмотреть pdf, мне лень вникать.

firkax ★★★★★
()
Ответ на: комментарий от ckotctvo

Я ж расписал потом, ты всегда отвечаешь недочитав?

Память в кеш читается по 64 байта, но между кешом и регистром ещё какая-то штука и она по 8 байт нарезана и мапится на разные линии кеша.

firkax ★★★★★
()
Ответ на: комментарий от unclestephen

в анекдоте про исправление ошибки в swap файле

А что там было?

question4 ★★★★★
()
Ответ на: комментарий от unclestephen

Это не самое лучшее что они сделали. Это кажется было первым их поделием, способным собирать высокопроизводительные серверы.

kirill_rrr ★★★★★
()

В процессорах Loongson для Linux-систем обнаружили

Что за процессоры такие? Если под loong64 винду скомпилируют, они её код исполнять откажутся?

mogwai ★★★★★
()
Ответ на: комментарий от firkax

ничего там не может мапиться. кэш всегда грузится целой линейкой. гугл же есть, почему надо такие банальные вещи объяснять.

кэш у них нарезан на банки по 8байт в ширину - обычная практика. несколько конкурирующих операций могут обращаться к разным банкам одновременно. Обычно это означает что к одной линейке можно обратиться если операции не пересекают границу 8n, и n у всех разное.

короче как я понял, у них есть priming instruction которая выбирает кэш-линейку в каком-то банке кэша, а затем они читают из другого банка кэша, и смещение в нем заполняется верно, а в других банках повторяется из прошлой инструкции. И это смещение не программный адрес а физический адрес регистра в банке кэша. Т.е. команды FLD реализованы как частный случай текущей инструкции VLD которая является маскированной версией XVLD.

Короче, есть кэш из 8 банков по 8 байт в ширину и N в длину. Он содержит N линеек кэша по 64 байт. Каждая линейка состоит из 8 раз по 8байт из каждого банка с одинаковым номером. Как пример как такое вообще может быть:

struct cache {
   enum { M=32, N = 64 }; 
   //8 банков по 2048 линеек, но для скорости они 
   //порезаны на подбанки по 64 линейки
   uint64 bank0[M][N];
   uint64 bank1[M][N];
   ...
   uint64 bank7[M][N];

   uint64 bank0_output[M];
   uint64 bank1_output[M];
   ...
   uint64 bank7_output[M];

   void load_from_mem_to_cache(uint1024 word, uint n) {
       bank0[n[6...10]][n[0...5]] = word[64*0+0...64*0+63];
       bank1[n[6...10]][n[0...5]] = word[64*1+0...64*1+63];
       ...
       bank7[n[6...10]][n[0...5]] = word[64*7+0...64*7+63];
   }
   void readbank0(n) {
       for(i = 0; i < M; ++i)
          bank0_output[i] = bank0[i][n[0...5]];
   }
   void readbank1(n) {...}
   ...
   void readbank7(n) {...}

   uint1024 vld(uint virt_addr,uint mask) {
       uint1024 out;

       //цикл один
       uint phys_reg;
       bool found;

       MMU(virt_addr, &found, &phys_reg); 

       if (mask0 & (1u<<0)) readbank0(virt_addr);
       if (mask0 & (1u<<1)) readbank1(virt_addr);
       ...
       if (mask0 & (1u<<7)) readbank7(virt_addr);

       //цикл 2
       if (found) {
           out[64*0+0...64*0+63] = select_phys_reg(bank0_output, phys_reg);
           out[64*1+0...64*1+63] = select_phys_reg(bank1_output, phys_reg);
           ...
           out[64*7+0...64*7+63] = select_phys_reg(bank7_output, phys_reg);
       }
       return out;
   }
   uint1024 xvld(uint n) {
       return vld(n,0xFF);
   }
};

собсна, это поведение типового non-aliasing VIPT-кэша. Когда мы читаем данные из кэша ДО решения MMU. т.е.(например) биты 0…2 вообще позже участвуют, биты 3…11 сразу читают наобум отовсюду чтоб хоть как-то успеть, а затем подходят биты из MMU и уже выбирают правильные ответы. Но если из банка читать не надо, оттуда не читают но ответ подбирают. А в bankX_output не только правильная строка, но и другие строки попали.

ckotctvo
()
Ответ на: комментарий от Vimmer

да в принципе если так подумать то у любой ошибки опасность нулевая )

Не знаю, как можно и можно ли из моих слов делать такой вывод. Ошибка есть, а серьёзность зависит от способа использования узла. Если используется однопользовательский режим, то воровать информацию не у кого, она и так доступна целиком этому пользователю. Тогда можно ошибку вообще не исправлять. Учитывая, о каком процессоре речь, вероятность использования его в таком режиме очень велика.

VIT ★★★
()

Нужно опрос сделать - кто пользуется лонгсонами, а кто эльбрусами.

Должны же мы знать, кого больше.

Saakx
()
Ответ на: комментарий от Saakx

Этот опрос активен прямо сейчас.

Или ты об этом и пытаешься намекнуть, а я не выкупаю за тройным слоем иронии?..

CrX ★★★★★
()
Ответ на: комментарий от seiken

Так кто ж тебе когда скажет?..

Впрочем, мне кажется, что скорее ошибка. Для бэкдора способ эксплуатации слишоком невнятный — хрен его массово по триггеру применишь.

CrX ★★★★★
()
Ответ на: комментарий от CrX

А зачем массово? Есть бизнес, который мутный какой-то, и надо его по тихому проверить. Без СМИ и истерик адвокатов. Серверочки изъять, по бырому снять инфу и отдать обратно.

seiken ★★★★★
()
Ответ на: комментарий от seiken

Если серверочки изъять, то ты либо сможешь прочитать с них данные и так, при физическом-то доступе, либо там всё зашифровано и для расшифровки нужен ключ, а не возможность непривилегированной программе прочитать данные кэша процессора. Малоприменимо для подобной ситуации.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от CrX

Если серверочки изъять, то ты либо сможешь прочитать с них данные и так, при физическом-то доступе

допустим, тебе нужны не только те данные, которые в данный момент на серваке есть, а ещё гигабайты трафика, в которых вскрыт уровень всяких ВПН, но прикладной уровень остаётся зашифрован. Без нахождения нужного ключа не обойтись.

seiken ★★★★★
()
Ответ на: комментарий от seiken

Я понимаю, что придумать, как и для чего эксплуатировать эту уязвимость, придумать несложно. Я ж не говорю, что она не существенна. Но для бэкдора, оставленного «на всякий случай» — слишком уж какая-то специфичная ситуация — это надо, чтобы именно вот так и было — и сервера-то ты изъял, и целиком они не зашифрованы, ты их можешь запустить, и вот только где-то там вовнутрях, интересное тебе, и надо из непривилигированного процесса это достать. Может ли быть такая ситуация? Ну конечно может. Но оставлять бэкдор чисто под неё имеет смысл разве что вот прям прицельно под какую-то заранее известную компанию с заранее известными серверами под изъятия. Банальная ошибка выглядит всё же вероятнее. Именно учитывая специфику уязвимости и её применимость.

CrX ★★★★★
()
Ответ на: комментарий от CrX

Ну ты в общем логичен в своих мыслях. Лучше всего такие бэкдоры делать включаемыми по фиксированному и секретному набору инструкций. Но китайцы ещё только учатся в искусстве маскировки, мистификаций и блефа именно с области электроники.

seiken ★★★★★
()

Loongson

Loongnix если пропатчить не поможет?

splinter ★★★★★
()
Ответ на: комментарий от sarumeister

Это не эксплойт, а штатная конфигурация проца. И xor этот надо делать из режима ядра.

firkax ★★★★★
()
Ответ на: комментарий от CrX

Через приложение ВиЧата снимаешь ключи, например. Бекдор в РедОс не нужен, можно на аудит отдавать)

BruteForce ★★★★
()
Ответ на: комментарий от seiken

Ну тут скорее тупое следование спецификации. Бездумное. Сказано undefined, значит пихай что под рукой окажется. Вот и напихали

ckotctvo
()
Ответ на: комментарий от ckotctvo

Это undefined там для того и написано, чтобы можно было пихать что угодно, не тратя на обработку ненужных битов ни одного лишнего транзистора. Так что следование не «тупое» а как раз все как планировалось. Вопросы безопасности там скорее всего не учитывались вообще, учитывалась скорость работы.

И вообще, какое ещё следование? Они сами спецификацию и писали, под свою разработку.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)

LoongLeak связана с особенностями выполнения инструкции FLD.S. В соответствии с руководством по архитектуре LoongArch она загружает из памяти 32-разрядное значение в 64-разрядный регистр с плавающей точкой, оставляя его старшие 32 бита в «неопределённом» состоянии.

Невероятно! Нет, это уже не детская ошибка. Это не недосмотр. Реально ведь, в спеке так и сказано:

FLD.S retrieves a word of data from the internal memory and writes it into the lower 32 bits of the
floating-point register fd. If the length of the floating-point register is 64 bits, the high 32-bit
value of fd is uncertain.

То есть, про багу они знали, и решили просто в спеку внести, а не фиксить.

В х86, правда, такие же перлы были, из-за чего в линуксе появились espfix/espfix64. Там точно так же в верхней части регистра оставался «мусор» от предыдущей операции. Но блин, то Интел с их 40летним легаси, а тут - новая архитектура…

anonmyous ★★★
()
Последнее исправление: anonmyous (всего исправлений: 1)
Ответ на: комментарий от firkax

Вопросы безопасности там скорее всего не учитывались вообще, учитывалась скорость работы.

Зануление неиспользуемых бит на скорость не повлияет вообще никак. Может быть это потребует нескольких дополнительных транзисторов, да и то не факт.

anonmyous ★★★
()
Ответ на: комментарий от anonmyous

Вероятно да, однако я не вижу никаких причин вводить «undefined» биты, кроме как сэкономить зануляющие транзисторы. Скорее всего причина была именно в этом, и там действительно вообще не подумали о том, что отдавать мусор из левого кеша - это утечка данных.

firkax ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.