O que são vdso e vsyscall?

Eu fiz o sudo cat /proc/1/maps -vv

Eu estou tentando fazer sentido da saída. Eu posso ver um monte de bibliotecas compartilhadas sendo mapeadas para o segmento de mapeamento de memory conforme o esperado.

 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 

No final há algo como

 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] 

O que vdso e vsyscall significam? é vsyscall a parte do kernel da memory? Seria ótimo se alguém pudesse lançar alguma luz sobre o assunto.

Os segmentos vsyscall e vDSO são dois mecanismos usados ​​para acelerar determinadas chamadas do sistema no Linux. Por exemplo, gettimeofday geralmente é chamado por meio desse mecanismo. O primeiro mecanismo introduzido foi o vsyscall , que foi adicionado como uma maneira de executar chamadas específicas do sistema que não precisam de qualquer nível real de privilégio para executar, a fim de reduzir a sobrecarga da chamada do sistema. Seguindo o exemplo anterior, tudo o que o gettimeofday precisa fazer é ler a hora atual do kernel. Há aplicativos que chamam gettimeofday frequentemente (por exemplo, para gerar timestamps), a ponto de se preocuparem com um pouco de sobrecarga. Para resolver essa questão, o kernel mapeia no espaço do usuário uma página contendo a hora atual e uma rápida implementação do gettimeofday (ou seja, apenas uma function que lê o tempo salvo no vsyscall ). Usando essa chamada de sistema virtual, a biblioteca C pode fornecer um gettimeofday rápido que não possui a sobrecarga introduzida pela alternância de contexto entre o espaço do kernel e o espaço do usuário normalmente introduzidos pelo modelo de chamada de sistema clássico INT 0x80 ou SYSCALL .

No entanto, este mecanismo vsyscall tem algumas limitações: a memory alocada é pequena e permite apenas 4 chamadas de sistema, e, mais importante e séria, a página vsyscall é alocada estaticamente para o mesmo endereço em cada processo, pois a localização da página vsyscall é pregado no kernel ABI. Esta alocação estática do vsyscall compromete o benefício introduzido pela randomização de espaço de memory comumente usada pelo Linux. Um invasor, após comprometer um aplicativo explorando um estouro de pilha, pode invocar uma chamada de sistema da página vsyscall com parâmetros arbitrários. Tudo o que ele precisa é o endereço da chamada do sistema, que é facilmente previsível, pois é alocado estaticamente (se você tentar executar novamente seu comando mesmo com aplicativos diferentes, notará que o endereço do vsyscall não muda). Seria bom remover ou pelo menos aleatoriamente a localização da página vsyscall para impedir esse tipo de ataque. Infelizmente, os aplicativos dependem da existência e do endereço exato dessa página, então nada pode ser feito.

Esse problema de segurança foi resolvido substituindo todas as instruções de chamada do sistema em endereços fixos por uma instrução de interrupção especial. Um aplicativo que tenta chamar a página vsyscall irá capturar o kernel, que então emulará a chamada do sistema virtual desejada no espaço do kernel. O resultado é uma chamada de sistema kernel emulando uma chamada de sistema virtual que foi colocada lá para evitar a chamada do sistema kernel em primeiro lugar. O resultado é um vsyscall que leva mais tempo para executar mas, crucialmente, não quebra a ABI existente. Em qualquer caso, a lentidão só será vista se o aplicativo estiver tentando usar a página vsyscall em vez do vDSO .

O vDSO oferece a mesma funcionalidade que o vsyscall, superando suas limitações. O vDSO (objects compartilhados dinamicamente vinculados virtuais) é uma área de memory alocada no espaço do usuário que expõe algumas funcionalidades do kernel no espaço do usuário de maneira segura. Isto foi introduzido para resolver as ameaças de segurança causadas pelo vsyscall . O vDSO é alocado dinamicamente, o que resolve as preocupações de segurança e pode ter mais de 4 chamadas do sistema. Os links vDSO são fornecidos através da biblioteca glibc. O vinculador vinculará a funcionalidade glibc vDSO , desde que essa rotina tenha uma versão de vDSO acompanhante, como gettimeofday . Quando seu programa é executado, se seu kernel não tiver suporte a vDSO , um syscall tradicional será feito.

Créditos e links úteis:

  • Tutorial incrível, como criar seu próprio vDSO .
  • vsyscall e vDSO, bom artigo
  • artigo útil e links
  • O que é o linux-gate.so.1?

Eu só quero acrescentar que agora em novos kernels, vDSO não é usado apenas para vDSO “seguros”, mas é usado para decidir qual mecanismo syscall é o método preferido para invocar um syscall no sistema.