LINUX.ORG.RU

Проблема флага O_DIRECT

 , , ,

Проблема флага O_DIRECT

3

6

Даже пользователь без прав администратора способен вызвать необратимую рассинхронизацию дисков.

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

Суть проблемы заключается в том, как пользовательские программы взаимодействуют с блочными устройствами при помощи O_DIRECT. Этот флаг позволяет выполнять прямой доступ к данным, минуя кеш ядра, что полезно для повышения производительности в ряде задач. Однако в случае программного RAID, такого как MD RAID, DRBD или LVM RAID, это приводит к тому, что каждый диск массива может получить разные данные, даже если они записываются с одного и того же указателя в пользовательском пространстве. В результате данные на отдельных устройствах перестают быть синхронизированными – массив остаётся «рабочим» с точки зрения системы, но фактически оказывается повреждённым.

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

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

Из всех файловых систем Linux, известны только две, не подверженные этому дефекту при использовании с программным RAID – это OpenZFS и Bcachefs. Остальные решения остаются потенциально уязвимыми. Проблема до сих пор числится как открытая и не имеет официального исправления.

>>> Подробности

★★★★★

Проверено: dataman ()
Последнее исправление: hobbit (всего исправлений: 3)
Ответ на: комментарий от alegz

В тикете:

  1. Сделать mdraid на хост-машине
  2. Запустить виртуалку с диском на этом mdraid
  3. В виртуалке сделать swap и заставить ее серьёзно свапаться

Итог — разваливается mdraid на хосте.

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

From: Linus Torvalds torvalds@osdl.org
Newsgroups: fa.linux.kernel
Subject: Re: O_DIRECT question
Date: Fri, 12 Jan 2007 21:19:22 UTC
… My point is that you can get basically ALL THE SAME GOOD BEHAVIOUR without having all the BAD behaviour that O_DIRECT adds.

For example, just the requirement that O_DIRECT can never create a file mapping, and can never interact with ftruncate would actually make O_DIRECT a lot more palatable to me. Together with just the requirement that an O_DIRECT open would literally disallow any non-O_DIRECT accesses, and flush the page cache entirely, would make all the aliases go away.

At that point, O_DIRECT would be a way of saying «we’re going to do uncached accesses to this pre-allocated file». Which is a half-way sensible thing to do.

But what O_DIRECT does right now is not really sensible, and the O_DIRECT propeller-heads seem to have some problem even admitting that there is a problem, because they don’t care.

A lot of DB people seem to simply not care about security or anything else.anything else. I’m trying to tell you that quoting numbers is pointless, when simply the CORRECTNESS of O_DIRECT is very much in doubt.

I can calculate PI to a billion decimal places in my head in .1 seconds. If you don’t care about the CORRECTNESS of the result, that is.

See? It’s not about performance. It’s about O_DIRECT being fundamentally broken as it behaves right now.

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

Угу, собственно цитата про конкретно эту проблему:

MD-RAID is susceptible to breakage from any programs that can issue O_DIRECT write request to it; ensure O_DIRECT issues are not relayed to the underlying storage (e.g., change the cache mode for VMs). Note that while the specific write pattern causing such a breakage can be considered an application bug, it has to be stated that there are a lot of bugs in current software, this behavior might be triggered by some (very rare) memory swapping pattern, and it can also be used as an attack vector, e.g. if the users of virtual guests are not fully trusted or if a virtual guest gets hijacked. While MD-RAID might not be the sole technology that is susceptible to this issue, it’s still noted explicitly as ZFS isn’t (it ignores O_DIRECT before 2.3 and supports it safely since 2.3) and MD-RAID makes repairing corruption a lot harder.

Автоперевод:

MD-RAID уязвим к сбоям из-за любых программ, способных выполнять к нему записи с флагом O_DIRECT; убедитесь, что операции O_DIRECT не проходят до нижележащего хранилища (например, смените режим кэширования для ВМ). Хотя конкретный шаблон записи, вызывающий такой сбой, можно считать ошибкой приложения, нужно учитывать, что в современном ПО много багов; это поведение может быть спровоцировано некоторыми (очень редкими) паттернами свопинга памяти и может использоваться как вектор атаки, например, если пользователям гостевых ВМ нельзя полностью доверять или если гость скомпрометирован. Хотя MD-RAID, возможно, не единственная технология, уязвимая к этой проблеме, важно, что ZFS — нет: она игнорирует O_DIRECT до версии 2.3 и безопасно поддерживает его начиная с 2.3, тогда как в MD-RAID исправлять повреждения значительно сложнее.

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

Это пример без использования фс. Перевести глаза на пример чуть ниже не судьба?

*** Variant: EXT3 or EXT4 on top of md0 ***

The step 2 can be extended by creating file system:

mkfs.ext3 /dev/md0
mkdir /tmp/ext3
mount /dev/md0 /tmp/ext3
./a.out /tmp/ext3/testfile1
vbindiff /tmp/mdadm{1,2}
greedyskoof
()
Ответ на: комментарий от legolegs

Вы, наверное, про то, какие блоки на каких дисках хранить? Это другое.

О чем я говорю: если из mdraid raid1 из 2 дисков читать параллельно, скажем, 16 блоков по 512 байт, то 8 блоков будет прочитано с одного диска и 8 с другого параллельно, и всё будет быстро.

Однако если читать по одному блоку по 8192 байт последовательно, то все 8192 данных будут прочитаны только с одного диска, и никакого ускорения не будет.
Банально dd if=/dev/md0 bs=1M of=/dev/null status=progress покажет скорость одного диска, потому что dd читает последовательно.

Аппаратные рейды умеют разделять запросы на два (или несколько) меньшим объёмом, а потом комбинировать данные. Вроде, вообще все аппаратные рейды умеют.

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

Да просто создав swap на этом же диске, не настраивая дополнительно.

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

по сути управление передаётся сразу драйверу блочного устройства

ты точно понимаешл о чём пишешь?
ты исходники ядра до этого посмотрел?

если бы дело было так как ты описываешь - невозможно было бы существование raid5/6 в mdadm, подумай на досуге почему

и нет причин почему в r1 и 10 это будут делать по другому чем в r5/6

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

вся эта тема - высосана из пальца

Date Wed, 10 Jan 2007 19:15:48 -0800 (PST)
From Linus Torvalds <>
Subject Re: O_DIRECT question

So O_DIRECT not only is a total disaster from a design standpoint (just look at all the crap it results in), it also indirectly has hurt better interfaces. For example, POSIX_FADV_NOREUSE (which could be a useful and clean interface to make sure we don’t pollute memory unnecessarily with cached pages after they are all done) ends up being a no-op ;/

Sad. And it’s one of those self-fulfilling prophecies. Still, I hope some day we can just rip the damn disaster out.

и там же чуть раньше ЕМНИП:

O_DIRECT is really fundamentally broken. There’s just no way to fix it sanely. Except by teaching people not to use it, and making the normal paths fast enough …

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

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

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

Т.е. когда вася, купивший VPS-ку разваливает хостовый рейд, это не баг ядра, так и запишем.

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

ниже написал мнение Линуса по поводу субд-писателей

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

всё так. собственно в мане на open всё доходчиво про этого и написано: «To guarantee synchronous I/O, O_SYNC must be used in addition to O_DIRECT»

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

@mumpster, вижу, ты поднял руку. Я так понимаю, тебе есть что возразить? Или то, что я столкнулся с этим багом, не вписывается в твой манямирок, и поэтому будет отброшено и проигнорировано?

Вставай, рассказывай. Я тебя очень внимательно слушаю.

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

примеры кстати совершенно некорректные.

вы часто пользуетесь /dev/loop + файло для создания зеркала?
по сути это пример подлога - обе части зеркала фактически лежат на одном и том же носителе и => физически не могут быть записаны одновременно, неизбежно на какой-то из них запись пойдёт после другого. чтобы это был реальный пример - зеркало должно быть создано на реально разных носителях.

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

у тя ошибка явно не O_DIRECT связана. скорее с косячной физикой.

странно что ты этого не понимаешь.

гонки конечно могут быть, но там очень специфичные условия нужны.

или ты тоже увлекаешься O_DIRECT? ССЗБ тогда

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

скорее с косячной физикой

Ну конечно, это физика, а не подтвержденный баг в ядре. Объясни мне, каким образом на исправных дисках и исправном хосте побились не просто какие-то сектора, а именно файлы? Размер файлов тот же, а внутри - мусор. Диски пишут то, что на них пришло. Если пришел мусор - будет записан мусор.

странно что ты этого не понимаешь

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

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

Пока не сделать echo check > /sys/block/md0/md/sync_action

Дак это должно часто стрелять, так как обычно raid1/10 включён TRIM.

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

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

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

да, я только что проверил

#mdadm -C /dev/md7 -l 1 -n 2 /dev/sd[fg]2
#mke2fs /dev/md7
#mount /dev/md7 /mnt
#/root/drbd_oos_test /mnt/testfile1
#umount /mnt
#mdadm –examine /dev/sdf2
#mount -o ro,offset=17825792 /dev/sdf2 /mnt
#md5sum /mnt/testfile1
9cf399394a450a6a0e6e92c15a566aee /mnt/testfile1
#umount /mnt
#mount -o ro,offset=17825792 /dev/sdg2 /mnt
#md5sum /mnt/testfile1
33c99ae5af30abb677fa5af35713c6ef /mnt/testfile1

если сравнить, то 60 тыщ разница:
#cmp -l /mnt/1/testfile1 /mnt/2/testfile1 |wc -l
60480

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

и? я тебе из mdadm.c первые строчки привёл, там 2001, пиши Нилу если чем-то недоволен

плюс какая разница как утилита называлась раньше?

она уже точно существовала 20 лет назад.

mumpster ★★★★★
()

Из всех файловых систем Linux, известны только две, не подверженные этому дефекту при использовании с программным RAID – это OpenZFS и Bcachefs. Остальные решения остаются потенциально уязвимыми. Проблема до сих пор числится как открытая и не имеет официального исправления.

Вспоминается, что говорил Шишкин (Reiser4) про подсистему ФС: что ее не берут в mainline в том числе и потому что оно делает действия вне стандартного API VFS. Я так понимаю, что и OpenZFS, и Bcachefs (и Reiser4+?) - это «ренегаты» и именно их это и не затронуло...

X-Pilot ★★★★★
()
Ответ на: комментарий от anc

У меня в детстве MySQL писал на файловую систему на drbd и последняя достаточно часто превращалась в тыкву. Из-за этого я научился дедать мастер-слейв кластеры мускла.

Возможно это и была причина …

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

Разный профиль нагрузки? Разный софт? Разная производительность дисков? Хз, что еще предложить.

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

вся эта тема - высосана из пальца

Ну как высосана. Вон у @liksys данные пострадали.

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

На момент написания новости автор мог и не видеть этот комментарий, там разница 1 час 15 минут. Давайте исправим.

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

сейчас некогда, потом попробую на 3-дисковом зеркале и на разных типах. но в целом давно понятно, что mdadm - только для рута и т.п. и свои данные там можно хранить только если админ локалхоста.

там ведь ещё bit rot и т.п. могут нарисоваться. а это никакими исправлениями в ПО не исправишь. только хранить избыточность и КС.

mumpster ★★★★★
()

не подверженные этому дефекту при использовании с программным RAID – это OpenZFS и Bcachefs

А разве где-то ещё используется что-то кроме ZFS?

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

А Нил то тут при чём? Копирайт относится к коду. Если код писался под что-то другое, а потом перенесён в другой проект, то дата копирайта не меняется. Но речь шла про ядерный драйвер, а не про утилиту mdadm. А до этой утилиты была другая. В исходниках этого mdctl/mdadm есть и такие строки:

   md_p.h : physical layout of Linux RAID devices
          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
          Copyright (C) 1998 Ingo Molnar
mky ★★★★★
()
Ответ на: комментарий от liksys

я могу лишь посочовствовать и скорее всего у вас другая ошибка проявляется (если это ошибка в ядре), но конкретно в случае по ссылке автор - ССЗБ, ибо поставив O_DIRECT, работает в режиме, где он сам должен отвечать за целостность своих данных по определению.

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

Нил тут причём как автор, указанный прямо в первых строчках программы. и речь изначально шла про то, что md используются уже много лет, точно больше 15 и проблемных случаев по сути не было ил ибыло мало. вот и всё. может я и mdctl пользовался, я уже не помню. какая разница если речь шла про другое?

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

Возможно. На сервере работало много разного софта, и сложно сказать, кто конкретно всё испортил. Может, баг с O_DIRECT - это звоночек чего-то другого, связанного с этим.

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

Вот именно, что речь шла про другое. А ваш пост выглядил как ребус. Сначала 25 лет и «он уже не был новостью». 2025-25 = 2000, но потом приводите в доказательство копирайт 2001 года. А с учётом того, что первые первые версии программы обычно никому не известны, получается, что 2002 год. Путаница. А можно было просто копипастнуть:

Although kernels prior to 2.0.35 shipped with some RAID support, it wasn’t until the release of 2.0.35 that support for RAID-1, RAID-4, and RAID-5 became available. The multiple devices (md) driver that provides kernel RAID support is currently at version 0.90. The latest stable kernels in the 2.0 and 2.2 series ship with an outdated version (0.36) of the software RAID driver. Patches for the 0.90 code are available for these older kernels (see the sections below on Kernel 2.2 and Kernel 2.0). Kernels prior to 2.0.35 ship with version 0.35 of the md driver and should not be used, except if you absolutely have to keep them in operation for legacy reasons.

А linux-2.0.35 — это 13-Jul-1998.

Но, с другой стороны, если возращаться к началу этой ветки, то O_DIRECT (since Linux 2.4.10), 23-Sep-2001, так что MD RAID с O_DIRECT отлаживают чуть больше 24 лет :)

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

ну может быть. но в 1998 году у меня на 2.0 были несколько другие проблемы и задачи - я делал backport с 2.2 для сетевух Tulip ибо они у нас были, а дров Бекер для них под 2.0 не написал.

только не спрашивайте почему нельзя было на 2.2 перелезть, я уже не вспомню, но причина была какая-то серьёзная.

и да - тогда серваки в наличии были достаточно слабы для md, даже зеркало ощутимо грузило P1. а PPro были только у мажоров.

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

не спрашивайте почему нельзя было на 2.2 перелезть

И не буду, я какой-то магией с 2.0.39 сразу на 2.4.0 или 2.4.1 перешёл, и ipchains только мельком у знакомых видел.

mky ★★★★★
()

Из всех файловых систем Linux, известны только две, не подверженные этому дефекту при использовании с программным RAID – это OpenZFS и Bcachefs.

Так BTRFS же тоже чексуммы должен проверять?

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

при внезапной необходимости смены софтварного стека не нужно будет все это дело мигрировать

И при исчерпании запаса аппаратных контроллеров на складе тоже не надо?

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