vsyscall in linux kernel

Programming, for all ages and all languages.
Post Reply
tylerbacon
Posts: 4
Joined: Sat Jun 18, 2011 3:36 am

vsyscall in linux kernel

Post by tylerbacon »

Hi, there

I recently studying about vsyscall, and I know that it's a kernel page mapped into user address space to accelerate system call
Therefore I try to go the tutorial in the website http://www.win.tue.nl/~aeb/linux/lk/lk-4.html(Sec4.6) to dump the page

Code: Select all


$ cat /proc/self/maps
...
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

/* get vsyscall page */
#include <unistd.h>
#include <string.h>

int main() {
        char *p = (char *) 0xffffffffff600000;
        char buf[4096];

        memcpy(buf, p, 4096);
        write(1, buf, 4096);

        return 0;
}

$ ./a.out > vsyscall
I dumped into one file but it showed that

Code: Select all

$ file vsyscall
vsyscall: data

$ objdump -d vsyscall
objdump: vsyscall: File format not recognized
i expect to get an ELF format file but objdump showed that it cannot recognized the format
i am sure that i dumped the right page, but why it turned out this unrecognized page
please help me to figure it out [-o<

OS: Fedora 14 x86_64
kernel : 2.6.35.6
User avatar
xenos
Member
Member
Posts: 1118
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: vsyscall in linux kernel

Post by xenos »

Did you try to open the output file / page dump with a hex editor to see what it actually contains?
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: vsyscall in linux kernel

Post by Velko »

tylerbacon wrote:i am sure that i dumped the right page
This is where you are wrong. Linux randomizes vsyscall page's location. If it seems to stay in one place for /bin/cat, it does not mean it will be there for your executable.

See for yourself - try to compile and run something like this:

Code: Select all

char *vsysc_addr, *vsysc_end;
FILE *vsyscf = fopen("/proc/self/maps", "r");
fscanf(vsyscf, "%x-%x", &vsysc_addr, &vsysc_end);
printf("%p - %p\n", vsysc_addr, vsysc_end);
fclose(vsyscf);
EDIT:
It was very late night, before going to sleep, when I posted this. Could not focus enough, sorry :oops:
The code above will not necessary show address of [vsyscall], just "some" mapping. You may want to read that file in a loop, searching for needed page.

Other than that - my point remains valid.
Last edited by Velko on Mon Aug 01, 2011 2:33 am, edited 1 time in total.
If something looks overcomplicated, most likely it is.
tylerbacon
Posts: 4
Joined: Sat Jun 18, 2011 3:36 am

Re: vsyscall in linux kernel

Post by tylerbacon »

Thanks for the replies

I have read that vsyscall page is fixed-mapped in user address space and the vdso is dynamically mapped
I dumped the vdso page by turning off address randomization, and then used objdump to disassemble it successfully

don't know why I failed in getting vsyscall page by using the same method
I have tried to dump vsyscall page by turning off address randomization, but it turned out the same result


text below is a part of vsyscall page that i dumped from 0xffffffffff600000

Code: Select all

0000000: 5548 89e5 4154 5348 89f3 4883 ec10 4885  UH..ATSH..H...H.
0000010: ff0f 849f 0000 0044 8b25 2201 0000 41f6  .......D.%"...A.                                                                                                                                                                       
0000020: c401 7404 f390 ebef 488b 0571 0100 0048  ..t.....H..q...H
0000030: 85c0 7409 833d 5901 0000 0075 0bb8 6000  ..t..=Y....u..`.
0000040: 0000 31f6 0f05 eb6e 4889 7de8 ffd0 488b  ..1....nH.}...H.
0000050: 1533 0100 0048 8b7d e84c 8b0d 4801 0000  .3...H.}.L..H...                                                                                                                                                                         
0000060: 4c8b 0549 0100 008b 354b 0100 008b 0d49  L..I....5K.....I                                                                                                                                                                         
0000070: 0100 0048 8917 8b15 1401 0000 4439 25bd  ...H........D9%.                                                                                                                                                                         
0000080: 0000 0075 924c 29c8 4c21 c048 0faf c648  ...u.L).L!.H...H                                                                                                                                                                        
0000090: d3e8 4801 d0eb 0948 ff07 482d 00ca 9a3b  ..H....H..H-...;                                                                                                                                                                        
00000a0: 483d ffc9 9a3b 77ef b9e8 0300 0031 d248  H=...;w......1.H                                                                                                                                                                        
00000b0: f7f1 4889 4708 4885 db74 0a48 8b05 d600  ..H.G.H..t.H....                                                                                                                                                                        
00000c0: 0000 4889 0359 5b5b 31c0 415c c9c3 0000  ..H..Y[[1.A\....                                                                                                                                                                        
00000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: vsyscall in linux kernel

Post by Combuster »

If you read the original text, it is for linux 2.5 (you are using 2.6!), and it is for 386s instead of 64-bit architectures. Also, amd64 is defined to have a fast system entry function, so there is no need for the kernel to dynamically generate code anymore.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: vsyscall in linux kernel

Post by jnc100 »

tylerbacon wrote:text below is a part of vsyscall page that i dumped from 0xffffffffff600000
That looks like x86_64 machine code. It starts 0x55 (push rbp), then the next opcodes are mov rbp, rsp. The large numbers of 0x48 are the rex.w prefix. Also, it ends c9 c3, which is leave, ret. I'd imagine if you did a direct dissassembly of that code (use the binary file format option to objdump) you'd get some code related to the vsyscall mechanism. Perhaps the way the information is stored has changed in recent kernels?

Regards,
John.
Hibou57
Posts: 4
Joined: Tue Apr 24, 2012 8:38 am
Contact:

Re: vsyscall in linux kernel

Post by Hibou57 »

`vsyscall` is obsolete, and is replaced by `linux-gate.so.1`, which is a virtual library mapped to the memory of each process. `linux-gate.so.1` abstracts the difference between architectures, so you do not have to invoke `int 80h` or `syscall` or `sysenter` or `epc`, instead, just the entry point provided by `linux-gate.so.1`.

Note `vsyscall` has been reported to be much slower than `linux-gate.so.1`, and some ones suspects this is on purpose. It also has been reported that `vsyscall` will issue a warning at runtime with future Linux kernel versions.

Look there for some talks on the topic:
Issue 1933: runtime: stop using vsyscall page on Linux. Jun 8, 2011

`linux-gate.so.1` is a vDSO, which you access via a reference provided in AUXV, which is a vector of parameters located in the stack, at an address above the argv and envp vectors provided to all Linux processes. Note its address (the one of `linux-gate.so.1`) is randomized for security reason, and will be different for each Linux process image: there will be no more magic static address to call in the future.

If you want to learn more on Linux vDSO, `linux-gate.so.1` and AUXV, here are some reference:
If you wish to play with some assembly, here is a sample assembly which print a short text on the standard output, not using `int 80h` nor `sysenter`, but `linux-gate.so.1` only, whose address it retrieve from AUXV passed in the stack at process initialization.

The original which I grabbed on the web, was for FASM, I changed it to NASM, I also changed some tiny things, but kept the original author's name :-p :

Code: Select all

; Luke McCarthy 2008-06-02
; Find linux-gate VDSO
; http://shaurz.wordpress.com/2008/06/02/finding-linux-gateso1-in-assembly/

; format ELF executable
; entry _start

SYS_EXIT  equ 1
SYS_WRITE equ 4
STDOUT equ 1
AT_SYSINFO equ 32

; segment readable executable

global _start

_start:
	mov ecx, [esp]         ; ecx = argc
	lea esi, [8+esp+ecx*4] ; esi = envp
.find_auxv:
	mov eax, [esi]
	lea esi, [esi+4]
	test eax, eax
	jnz .find_auxv
	; esi = auxv
.find_sysinfo:
	mov eax, [esi]
	cmp eax, AT_SYSINFO
	je .found_sysinfo
	lea esi, [esi+8]
	test eax, eax
	jnz .find_sysinfo
	jmp .not_found_sysinfo
.found_sysinfo:
	mov ebp, [esi+4]  ; ebp = sysinfo
	mov eax, SYS_WRITE
	mov ebx, STDOUT
	mov ecx, msg_succ
	mov edx, msg_succ_size
	call ebp  ; syscall
	mov eax, SYS_EXIT
	xor ebx, ebx
	jmp ebp   ; syscall
.not_found_sysinfo:
	mov eax, SYS_WRITE
	mov ebx, STDOUT
	mov ecx, msg_fail
	mov edx, msg_fail_size
	int 0x80
	mov eax, SYS_EXIT
	mov ebx, 1
	int 0x80

; segment readable

msg_succ db "linux gate found :-)", 10
msg_succ_size equ $ - msg_succ
msg_fail db "linux gate not found :-(", 10
msg_fail_size equ $ - msg_fail
Post Reply