Cos'e' linux-gate.so.1 ?

Storia della sysenter e del kernel 2.6

Quando usi "ldd" per verificare le dipendenze di un'eseguibile, in una distro recente noti una dipendenza da una fantomatica libreria chiamata linux-gate.so.xxx.

Esempio:

$ ldd /bin/sh
        linux-gate.so.1 =>  (0xffffe000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7fb2000)
        libc.so.6 => /lib/libc.so.6 (0xb7e7c000)
        /lib/ld-linux.so.2 (0xb7fba000)


sulla mia Slacky :)

Provate a cercare quel file. Su tutto il filesystem e non lo troverete!

Ma come e' possibile avere una dipendenza da una libreria che non esiste?

Quella e' un DSO, un oggetto sherato dal kernel ad un indirizzo fisso.

Non ci credete allora provate..
con

$ cat /proc/self/maps
-- snip --
7e88000-b7e89000 rwxp b7e88000 00:00 0
b7e89000-b7fb8000 r-xp 00000000 08:03 8856588    /lib/libc-2.3.5.so
b7fb8000-b7fb9000 r-xp 0012e000 08:03 8856588    /lib/libc-2.3.5.so
b7fb9000-b7fbc000 rwxp 0012f000 08:03 8856588    /lib/libc-2.3.5.so
b7fbc000-b7fbe000 rwxp b7fbc000 00:00 0
b7fc2000-b7fd9000 r-xp 00000000 08:03 8856915    /lib/ld-2.3.5.so
b7fd9000-b7fdb000 rwxp 00016000 08:03 8856915    /lib/ld-2.3.5.so
bfac3000-bfad9000 rw-p bfac3000 00:00 0          [stack]
ffffe000-fffff000 ---p 00000000 00:00 0          [vdso]
-- snip --


L'ultima riga identifica un virtualDSO, e' il linux-gate!!

Verifichiamo che nello spazio di indirizzamento a 32 bit per ogni processo esso e' dislocato come indicato sopra tra ffffe000-fffff000, cioe' se considerate che ogni pagina e grande 4KB, 4096 bytes, che corrisponde alla penultima pagina.

Visto che in ogni processo esso e' dislocato allo stesso indirizzo virtuale, e' facile con 'dd' sbatterlo su un file e capire cosa e'!

$ dd if=/proc/self/mem of=linux-gate.mydso bs=4096 skip=1048574 count=1
1+0 records in
1+0 records out


(PS. ragionate sul preche' di 1048574 )

ora che l'ho estratto potrei fare un 'file' per vedere cosa e':

$ file -b linux-gate.mydso
ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), stripped


oppure un objdump:

$ objdump -T linux-gate.mydso


da quest'ultimo comando noto che vi sono due simboli che rappresentano entry point per system-call (chiamate di sistema, quindi al kernel, si passa da userspace a kernel space): "rt_sigreturn/sigreturn"

Ma veniamo al dunque, a cosa serve tutto questo marchingegno?

Inizialmente le systemcall avvenivano per esempio in DOS sollevando attraverso l'interrupt int 0x21 o sotto linux e svariati Unix attraverso l'interrupt int 0x80;

Ci si accorse che sollevare un'interrupt per ogni syscall era comunque oneroso. Intel si accorse del problema e ha introdotto due nuove funzioni del microprocessore chiamate "sysenter e sysexit". Comode e veloci per fare una system-call e uscirne senza sollevare interrupt.

Questa funzione implementata fu implementata sui pentium III per la prima volta e apparve nei kernel linux verso la fine del 2002 durante lo sviluppo del kernel 2.5.

Non ci credere, ora proviamo a fare:

$ objdump -d --start-address=0xffffe400 --stop-address=0xffffe414 linux-gate.mydso

linux-gate.mydso:     file format elf32-i386

Disassembly of section .text:

ffffe400 <__kernel_vsyscall>:
ffffe400:       51                      push   %ecx
ffffe401:       52                      push   %edx
ffffe402:       55                      push   %ebp
ffffe403:       89 e5                   mov    %esp,%ebp
ffffe405:       0f 34                   sysenter
ffffe407:       90                      nop  
ffffe408:       90                      nop  
ffffe409:       90                      nop  
ffffe40a:       90                      nop  
ffffe40b:       90                      nop  
ffffe40c:       90                      nop  
ffffe40d:       90                      nop  
ffffe40e:       eb f3                   jmp    ffffe403 <__kernel_vsyscall+0x3>
ffffe410:       5d                      pop    %ebp
ffffe411:       5a                      pop    %edx
ffffe412:       59                      pop    %ecx
ffffe413:       c3                      ret

eccola la'
ffffe405: 0f 34 sysenter

La modalita' preferita di invocare una system call viene determinata dal kernel a tempo di boot. Evidentemente la mia macchina usa la sysenter. Su una macchina piu' vecchia che non la implementa a livello di microprocessore potresti trovare la piu' lenta "int 0x80" al suo posto.

Nei kernel 2.4 non era utilizzata tale funzione per fare le syscall. Percio' tale dipendenza di un eseguibile da una fantomatica libreria linux-gate e' visibile solo se sta girando un kernel 2.6.

Microsoft inizio' ad usare la sysenter nel suo kernel a partire da WindowsXP.

Luca Lopomo

La prima versione del documento e' stata postata da me sul forum del Ticino Linux User Group (Lugano)  ed e' consultabile: http://www.tilug.ch/forum/viewtopic.php?t=266

Privacy Policy