Могу ли я исключить, что SIGBUS вызван "незначительной ошибкой страницы"? (В журнале ядра нет сбоя выделения ресурсов)



Мотивация



Я пытаюсь улучшить свое понимание ошибкиSIGBUS в Xwayland . Это было замечено несколькими пользователями Fedora Linux примерно с 20 февраля 2018 года, с Xwayland 1.19.6-5.fc27.x86_64 и ядром Linux 4.15.3-300.fc27.x86-64.

К сожалению, у меня нетядра "segfault" log message (или эквивалента для SIGBUS). Xwayland имеет какой-то беспредметный код, который ловушки роковой сигнал. Но я могу видеть.siginfo путем отладки coredump, и это, кажется, будет почти так же хорошо.



Определение



Я понимаю, что "главная ошибка страницы" возникает, когда страница виртуальной памяти недоступна в оперативной памяти и должна быть прочитана с диска. Я думаю, что меня особенно интересуют страницы, поддерживаемые файловой системой ext4 (например, без прямого доступа к блокирующим устройствам) для этого вопроса.

Поэтому "незначительная ошибка страницы" - это когда нет необходимости в доступе к диску. Я предполагаю, что разница довольно четко определена, потому что Linux предоставляет счетчики для мажора и минора ошибка страницы.

Мой вопрос



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



Согласно coredump и дизассемблированию, программа считывает память, когда получает SIGBUS, а не записывает ее. Адрес ошибки в siginfo->si_addr находится в сопоставленном системном исполняемом файле, который не может быть записан пользователем, и адрес, по-видимому, находится в пределах текущей длины файла. На самом деле при отладке coredump, я прочитал очень убедительные значения из адреса памяти. Похоже, процесс генерации coredump не испытывал трудностей с чтением этого адреса :-(.

Я также уверен в исключении случая " недопустимого выравнивания адресов "(BUS_ADRALN), потому что siginfo->si_code-это 2, т. е. BUS_ADRERR,"несуществующий физический адрес". Кроме того, потому что я на x86, который в большинстве случаев разрешает не выровненный доступ, и ловушка не находится ни в одной расширенной инструкции SSE.



Я рассмотрел, что такое ядро обычно отвечает за, когда он обрабатывает ошибку страницы, которую он определяет как "незначительную". Я предполагаю, что незначительные ошибки могут не выделять память и, следовательно, вызывать SIGBUS. Тем не менее, я полагаю, что заметил бы такой сбой распределения:



У меня есть много свободного свопа, чтобы вытеснить страницы пользователей, и я не заметил обычного очевидного замедления, которое происходит, когда моя система начинает подкачку. Авария произошла через несколько секунд после того, как ноутбук был переведен из режима ожидания в оперативную память, чего не произошло. были достаточно долго, чтобы заполнить 8 ГБ свопа даже при ~100 МБ/с.
Я также не видел, чтобы в журналах ядра появлялся убийца dread Out of Memory (OOM), как я ожидал бы, если бы ядро не выделило фрейм страницы или таблицу страниц.



Существует ли какая-то другая возможность того, что незначительная ошибка страницы могла привести к сбою и вызвать SIGBUS? Т. е. есть ли какая-то причина, которую я бы не заметил, когда искал ошибки в журнале ядра? И что может иметь быстрое начало?



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



Скрытая мотивация



Я действительно хотел бы пропустить случай для незначительных ошибок страницы. Потому что ужасающая обратная сторона этого заключается в том, что я не вижу, как этот SIGBUS мог быть вызван жесткой стороной ошибки страницы. Некоторые из нас, пользователей, имеют очень похожие ошибки, начиная с нескольких месяцев назад. В моих журналах ядра нет ошибки ввода-вывода. Во время нормальной работы у меня есть отсутствие ошибок ввода-вывода при чтении указанного файла. У меня нет ошибок при запуске rpm --verify --all или при запуске расширенного интеллектуального теста на жестком диске. К сожалению, у меня очень мало подозреваемых. Самое близкое подозрение, которое у меня есть, - это обновление ядра, которое я, очевидно, предпочел бы исключить; даты точно не доказывают этого, но это не полностью исключено. Следующий ближайший в датах-это обновление микрокода years; похоже, что это будет еще труднее закрепить.



Известные причины незначительные ошибки страницы




  1. логически это звучит так, как будто незначительные ошибки страницы происходят при реализации copy-on-write для отображений MAP_PRIVATE.

  2. следует также включать чтение ошибок в /dev/нуль или MAP_ANONYMOUS, предполагая, что ядра сделал не реализовать их в , читая общий ноль страницы, а не воплощать их в жизнь, чтобы выделить страницы для весь отображения немедленно.


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


    MAP_NONBLOCK (начиная с Linux 2.5.46)



    Этот флаг имеет смысл только в сочетании с MAP_POPULATE.
    Не выполняйте чтение вперед: создавайте записи таблиц страниц только для
    страницы, которые уже присутствуют в оперативной памяти. Начиная С Linux 2.6.23, это
    флаг заставляет MAP_POPULATE ничего не делать. Однажды, комбина‐
    ного map_populate и MAP_NONBLOCK может быть переопределен.







EDIT: дальнейшие выдержки, детализирующие вышеизложенное



Комментатор попросил более конкретные детали, чтобы уточнить адрес и инструкцию по неисправности. Есть много выдержек в начальной ссылке https://bugzilla.redhat.com/show_bug.cgi?id=1557682



Неисправность изменяется следующим образом: описано в ссылке на ошибку. Вот свежие выдержки из недавнего примера.



$ gdb 2018-03-21.core
...
Core was generated by `/usr/bin/Xwayland :0 -rootless -terminate -core -listen 4 -listen 5 -displayfd'.
Program terminated with signal SIGBUS, Bus error.
#0 _dl_fixup (l=0x7fc0be2e0130, reloc_arg=203) at ../elf/dl-runtime.c:73
73 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
[Current thread is 1 (Thread 0x7fc0be29fa80 (LWP 1918))]
(gdb) p $_siginfo.si_signum
$1 = 7
(gdb) p $_siginfo.si_code
$2 = 2
(gdb) p $_siginfo._sifields._sigfault.si_addr
$3 = (void *) 0x41bd80
(gdb) disassemble
Dump of assembler code for function _dl_fixup:
0x00007fc0be0c8bd0 <+0>: push %rbx
0x00007fc0be0c8bd1 <+1>: mov %rdi,%r10
0x00007fc0be0c8bd4 <+4>: mov %esi,%esi
0x00007fc0be0c8bd6 <+6>: lea (%rsi,%rsi,2),%rdx
0x00007fc0be0c8bda <+10>: sub $0x10,%rsp
0x00007fc0be0c8bde <+14>: mov 0x68(%rdi),%rax
0x00007fc0be0c8be2 <+18>: mov 0x8(%rax),%rdi
0x00007fc0be0c8be6 <+22>: mov 0xf8(%r10),%rax
0x00007fc0be0c8bed <+29>: mov 0x8(%rax),%rax
0x00007fc0be0c8bf1 <+33>: lea (%rax,%rdx,8),%r8
0x00007fc0be0c8bf5 <+37>: mov 0x70(%r10),%rax
=> 0x00007fc0be0c8bf9 <+41>: mov 0x8(%r8),%rcx
(gdb) p/x $r8
$4 = 0x41bd78
(gdb) p/x $r8 + 8
$5 = 0x41bd80


Примечание эта инструкция извлекает значение reloc->r_info в соответствии с выделенной исходной строкой.



(gdb) p reloc
$6 = (const Elf64_Rela * const) 0x41bd78
(gdb) p &reloc->r_info
$7 = (Elf64_Xword *) 0x41bd80
(gdb) p *reloc
$8 = {r_offset = 8443504, r_info = 936302870535, r_addend = 0}


Адрес сбоя попадает в текстовое отображение ниже (из файла maps, захваченного abrtd):



00400000-0060b000 r-xp 00000000 fd:00 1708508                            /usr/bin/Xwayland
0080a000-0080d000 r--p 0020a000 fd:00 1708508 /usr/bin/Xwayland
0080d000-00817000 rw-p 0020d000 fd:00 1708508 /usr/bin/Xwayland

$ size -x /usr/bin/Xwayland
text data bss dec hex filename
0x209ffb 0xbe9d 0x1f3e0 2314872 235278 /usr/bin/Xwayland
678   2  

2 ответов:

У меня, конечно, есть какая-то Ошибка в ядре, если только это не ошибка в самотестировании ядра.

EDIT: хм, на самом деле кажется, что другие заметили сбой GS selftests недавно, но он уже присутствовал в старых ядрах, а также появляется на процессорах AMD. На данный момент, по-видимому, нет заключения о том, как это исправить. https://lkml.org/lkml/2018/1/26/436

Так что это не ошибка сама по себе, хотя я не могу исключить, что это Ошибка GS вызывает более заметные поломки, когда PTI включен или что-то еще.

$ uname -r
4.15.10-300.fc27.x86_64

$ git describe --all
heads/4.15.10
$ cat ./Documentation/x86/pti.txt
...
2. Run several copies of all of the tools/testing/selftests/x86/ tests
   (excluding MPX and protection_keys) in a loop on multiple CPUs for
   several minutes.  These tests frequently uncover corner cases in the
   kernel entry code.  In general, old kernels might cause these tests
   themselves to crash, but they should never crash the kernel.

$ cd tools/testing/selftests/x86
$ make
...

В 4X терминалах, чтобы соответствовать моим 4X аппаратным потокам:

sh -c ' while true; do for i in *; do if test -x $i; then ./$i || exit; fi ; done; done '

Сбои быстро появляются:

[RUN]   ARCH_SET_GS(0x200000000), then schedule to 0x200000000
    Before schedule, set selector to 0x3
    other thread: ARCH_SET_GS(0x200000000) -- sel is 0x0
[FAIL]  GS/BASE changed from 0x3/0x0 to 0x0/0x0

Также

[RUN]   Executing 6-argument 32-bit syscall via VDSO
[WARN]  Flags before=0000000000200ed7 id 0 00 o d i s z 0 a 0 p 1 c
[WARN]  Flags  after=0000000000200682 id 0 00 d i s 0 0 1 
[WARN]  Flags change=0000000000000855 0 00 o z 0 a 0 p 0 c
[OK]    Arguments are preserved across syscall
[NOTE]  R11 has changed:0000000000200682 - assuming clobbered by SYSRET insn
[OK]    R8..R15 did not leak kernel data
[RUN]   Executing 6-argument 32-bit syscall via INT 80
[OK]    Arguments are preserved across syscall
[OK]    R8..R15 did not leak kernel data
[RUN]   Running tests under ptrace
[RUN]   Executing 6-argument 32-bit syscall via VDSO
[WARN]  Flags before=0000000000200ed7 id 0 00 o d i s z 0 a 0 p 1 c
[WARN]  Flags  after=0000000000200686 id 0 00 d i s 0 0 p 1 
[WARN]  Flags change=0000000000000851 0 00 o z 0 a 0 0 c
[OK]    Arguments are preserved across syscall
[NOTE]  R11 has changed:0000000000200686 - assuming clobbered by SYSRET insn
[OK]    R8..R15 did not leak kernel data
[RUN]   Executing 6-argument 32-bit syscall via INT 80
[OK]    Arguments are preserved across syscall
[OK]    R8..R15 did not leak kernel data
Warning: failed to find getcpu in vDSO
[RUN]   Testing getcpu...
[OK]    CPU 0: syscall: cpu 0, node 0
[OK]    CPU 1: syscall: cpu 1, node 0
[OK]    CPU 2: syscall: cpu 2, node 0
[OK]    CPU 3: syscall: cpu 3, node 0
[RUN]   Testing getcpu...
[OK]    CPU 0: syscall: cpu 0, node 0 vdso: cpu 0, node 0 vsyscall: cpu 0, node 0
[OK]    CPU 1: syscall: cpu 1, node 0 vdso: cpu 1, node 0 vsyscall: cpu 1, node 0
[OK]    CPU 2: syscall: cpu 2, node 0 vdso: cpu 2, node 0 vsyscall: cpu 2, node 0
[OK]    CPU 3: syscall: cpu 3, node 0 vdso: cpu 3, node 0 vsyscall: cpu 3, node 0
[NOTE]  failed to find getcpu in vDSO
[RUN]   test gettimeofday()
    vDSO time offsets: 0.000006 0.000000
[OK]    vDSO gettimeofday()'s timeval was okay
[RUN]   test time()
[FAIL]  vDSO returned the wrong time (1522063297 1522063296 1522063297)

Спасибо всем за Вашу поддержку. Это действительно была временная ошибка ввода-вывода. Похоже, что путь sigbus read-fault не обязательно регистрирует что-либо в журнале ядра, в отличие от случаев, которые я привык видеть для ошибок ввода-вывода.

Https://marc.info/?l=linux-ide&m=152232081917215&w=2

V4. 15 прерывистые ошибки при приостановке / возобновлении

Всем, кто ждет другого шоу, чтобы упасть на работу SATA LPM...

Я нашел кое-что, что, по крайней мере, в же район. Это вызвало а fsck в моей системе 2 дня назад. Свидетельства говорят о том, что это происходило на многих другая техника. Я чувствовал, что это достаточная причина, чтобы предупредить тебя. :).

Я проверил, и мне кажется, что LPM не включен во время выполнения, даже при работе от аккумулятора. Мои ошибки все на приостановить / возобновить, так что может быть, это поведение изменилось в то же самое время?

Он не всегда отображается в журналах ядра. То, что я впервые заметил, было таинственный СИГБУС, что убивает Xwayland (а значит и всего гнома сессия) по возобновлению из приостановки. Я был удивлен, узнав, что это SIGBUS может произойти, не оставляя ничего похожего на ошибки чтения, которые я привык видеть в журнале ядра!

Мои coredumps показывают, что адрес ошибки SIGBUS-это прочитанная инструкция внутри программного кода Xwayland. В отчеты различаются по одна и та же цепочка вызовов-общим фактором является то, что они всегда находятся на первая инструкция функции. Я так и предполагаю варьируется в зависимости от какая страница в данный момент не находится в ядре, и, следовательно, запускает сбой запрос на чтение.

Есть сотни обратных следов вдоль этой же цепочки вызовов от другие пользователи, автоматически сообщаемые Fedora, выглядят так же. По крайней мере, пока у нас нет для них ничего более правдоподобного. Я признаю это. забавно, что Xwayland настолько заметен, и я не был затоплен с SIGBUS в других процессах, но я стою на этом анализе.

Эти сбои начались в течение 24 часов после обновления Fedora до ядра В4.15.

Ошибка Fedora для Xwayland SIGBUS: https://bugzilla.redhat.com/show_bug.cgi?id=1553979

Мой дубликат ошибки я спамил с озадаченными комментариями: https://bugzilla.redhat.com/show_bug.cgi?id=1557682

Самая ранняя и самая большая из множества корзин отчетов о сбоях:

Ошибка файловой системы EXT4:

Mar 27 11:28:30 alan-laptop kernel: PM: suspend exit
...
Mar 27 11:28:30 alan-laptop kernel: EXT4-fs error (device dm-2):  ext4_find_entry:1436: inode #5514052: comm thunderbird: reading directory lblock 0
Mar 27 11:28:30 alan-laptop kernel: Buffer I/O error on dev dm-2, logical block 0, lost sync page write
(this marked the FS as needing fsck on next boot)

Чаще всего он регистрирует следующие ошибки подкачки:

Mar 02 18:47:03 alan-laptop kernel: Restarting tasks ...
Mar 02 18:47:03 alan-laptop kernel: Read-error on swap-device (253:1:836184)
Mar 02 18:47:06 alan-laptop kernel: Read-error on swap-device (253:1:580280)

Состояние LPM моего ноутбука, даже после отключения питания от сети переменного тока:

$ head /sys/class/scsi_host/host*/link_power_management_policy
==> /sys/class/scsi_host/host0/link_power_management_policy <==
max_performance

==> /sys/class/scsi_host/host1/link_power_management_policy <==
max_performance

Мой ноутбук-Dell Lattitude E5450. Процессор-i5-5300U (A Broadwell).

Comments

    Ничего не найдено.