я сделал sudo cat /proc/1/maps -vv
Я пытаюсь разобраться в выводе и вижу, как много разделяемых библиотек сопоставляются с сегментом отображения памяти, как и ожидалось.
7f3c00137000-7f3c00179000 r-xp 00000000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00179000-7f3c00379000 ---p 00042000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c00379000-7f3c0037a000 r--p 00042000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037a000-7f3c0037b000 rw-p 00043000 08:01 21233923 /lib/x86_64-linux-gnu/libdbus-1.so.3.5.8
7f3c0037b000-7f3c00383000 r-xp 00000000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00383000-7f3c00583000 ---p 00008000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00583000-7f3c00584000 r--p 00008000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00584000-7f3c00585000 rw-p 00009000 08:01 21237216 /lib/x86_64-linux-gnu/libnih-dbus.so.1.0.0
7f3c00585000-7f3c0059b000 r-xp 00000000 08:01 21237220 /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0059b000-7f3c0079b000 ---p 00016000 08:01 21237220 /lib/x86_64-linux-gnu/libnih.so.1.0.0
7f3c0079b000-7f3c0079c000 r--p 00016000 08:01 21237220 /lib/x86_64-linux-gnu/libnih.so.1.0.0
Ближе к концу есть что-то вроде
7f3c0165b000-7f3c0177e000 rw-p 00000000 00:00 0 [heap]
7fff97863000-7fff97884000 rw-p 00000000 00:00 0 [stack]
7fff97945000-7fff97946000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Что значит vdso
и vsyscall
? vsyscall - это часть памяти ядра? Было бы здорово, если бы кто-нибудь мог пролить свет на эту проблему.
Ответы:
В vsyscall и vDSO сегменты два механизма , используемые для ускорения некоторых системных вызовов в Linux. Например,
gettimeofday
обычно вызывается через этот механизм. Первым представленным механизмом был vsyscall , который был добавлен как способ выполнения определенных системных вызовов, для выполнения которых не требуется никакого реального уровня привилегий, чтобы уменьшить накладные расходы на системные вызовы. Следуя предыдущему примеру, все, чтоgettimeofday
нужно сделать, это прочитать текущее время ядра. Есть приложения, которые вызываютgettimeofday
часто (например, для генерации меток времени) до такой степени, что они заботятся даже о небольших накладных расходах. Чтобы решить эту проблему, ядро отображает в пользовательское пространство страницу, содержащую текущее время и быстрыйgettimeofday
реализация (т.е. просто функция, которая считывает сэкономленное время в vsyscall ). Используя этот виртуальный системный вызов, библиотека C может обеспечить быстрый,gettimeofday
который не имеет накладных расходов, связанных с переключением контекста между пространством ядра и пространством пользователя, обычно вводимым классической моделью системного вызоваINT 0x80
илиSYSCALL
.Однако этот механизм vsyscall имеет некоторые ограничения: выделяемая память мала и позволяет только 4 системных вызова, и, что более важно и серьезно, страница vsyscall статически выделяется по одному и тому же адресу в каждом процессе, поскольку расположение страницы vsyscall является прибил в ядре ABI. Это статическое распределение vsyscall ставит под угрозу преимущество, предоставляемое рандомизацией пространства памяти, обычно используемым в Linux. Злоумышленник, скомпрометировав приложение путем использования переполнения стека, может вызвать системный вызов из vsyscall.страница с произвольными параметрами. Все, что ему нужно, это адрес системного вызова, который легко предсказуем, поскольку он статически распределен (если вы попытаетесь снова запустить свою команду даже с другими приложениями, вы заметите, что адрес vsyscall не изменится). Было бы неплохо удалить или хотя бы случайным образом расположить страницу vsyscall, чтобы предотвратить этот тип атаки. К сожалению, приложения зависят от наличия и точного адреса этой страницы, поэтому ничего не поделаешь.
Эта проблема безопасности устранена путем замены всех инструкций системных вызовов по фиксированным адресам специальной инструкцией прерывания. Приложение, пытающееся вызвать страницу vsyscall, попадет в ловушку ядра, которое затем будет имитировать требуемый виртуальный системный вызов в пространстве ядра. Результатом является системный вызов ядра, имитирующий виртуальный системный вызов, который был помещен туда, чтобы избежать системного вызова ядра в первую очередь. Результатом является вызов vsyscall, выполнение которого занимает больше времени, но, что особенно важно, не нарушает существующий ABI. В любом случае замедление будет видно только в том случае, если приложение пытается использовать страницу vsyscall вместо vDSO .
VDSO предлагает ту же функцию, что и vsyscall, преодолевая свои ограничения. VDSO (виртуальные динамически связанные общие объекты) - это область памяти, выделенная в пользовательском пространстве, которая безопасным образом предоставляет некоторые функции ядра в пользовательском пространстве. Это было введено для устранения угроз безопасности, вызванных доменом
vsyscall
. VDSO выделяется динамически, что решает проблемы безопасности и может иметь более 4 системных вызовов. В vDSO ссылки предоставляются через библиотеку GLibC. Компоновщик свяжет функциональность glibc vDSO при условии, что такая процедура имеет сопутствующую версию vDSO , напримерgettimeofday
. Когда ваша программа выполняется, если в вашем ядре нет vDSO support, будет выполнен традиционный системный вызов.Источники и полезные ссылки:
источник
Я просто хочу добавить, что теперь в новых ядрах
vDSO
он не используется только для «безопасных» системных вызовов, но используется для определения того, какой механизм системных вызовов является предпочтительным методом для вызова системного вызова в системе.источник