logo

Linux - vDSO (Virtual Dynamic Shared Object)

vDSO (virtual Dynamic Shared Object) is a small shared library that the Linux kernel automatically maps into the address space of every user-space process.

Its primary purpose is to speed up specific system calls by allowing them to execute in user space, avoiding the "expensive" transition between user mode and kernel mode.

The Problem: The High Cost of System Calls

Normally, when a program needs to do something that requires the kernel (like reading a file or getting the current time), it performs a system call (syscall). This involves:

  1. Context Switching: The CPU switches from "User Mode" to "Kernel Mode."
  2. Privilege Change: The kernel validates the request and executes it.
  3. Context Switching back: The CPU switches back to "User Mode."

This process is relatively slow because it involves saving CPU registers, flushing caches, and switching memory protection levels. For simple tasks that are called thousands of times per second (like checking the time), this overhead significantly hurts performance.

The Solution: vDSO

The kernel realizes that some information (like the current time) can be updated by the kernel in a shared memory page that the user-space process can simply read.

Instead of a full syscall, the process calls a function inside the vDSO. This function looks at the shared memory, does a few calculations, and returns the result—all without ever leaving "User Mode."

Common Functions in vDSO

Not every system call can be a vDSO function. Only calls that don't require high-privilege hardware interaction are candidates. Common examples include:

  • gettimeofday()
  • time()
  • clock_gettime()
  • getcpu() (to see which CPU core the process is running on)

How it works (The Mechanics)

  • ELF Format: The vDSO is a standard ELF (Executable and Linkable Format) shared library, just like libc.so.
  • Automatic Injection: You don't have to link against vDSO manually. The dynamic linker (ld.so) finds it because the kernel passes its location to the process via the Auxiliary Vector when the program starts.
  • ASLR Support: Unlike its predecessor (vsyscall), the vDSO is mapped at a random address in memory every time a process starts, which makes it more secure against memory-corruption exploits.

vDSO vs. vsyscall

Before vDSO, there was vsyscall.

  • vsyscall: Was at a fixed memory address. This was bad for security because hackers knew exactly where it was. It was also limited to only 4 function slots.
  • vDSO: Replaced vsyscall. It is dynamic, supports ASLR, and can hold as many functions as the kernel developers want to add.

How to see it on your system

You can see the vDSO mapped in any running process. Try running this command in your terminal:

cat /proc/self/maps | grep vdso

You will see an output similar to this: 7ffca37e5000-7ffca37e7000 r-xp 00000000 00:00 0 [vdso]

You can also see it listed as a dependency for any binary using ldd:

ldd /bin/ls

You will see linux-vdso.so.1 at the top of the list, usually pointing to a memory address rather than a file on disk.

Why is an .lds file critical for vDSO?

vDSO is a tiny, "fake" shared library. Because it is so specialized, a standard linker script won't work. The vDSO .lds file ensures:

  • Size Minimization: It discards unnecessary sections that a normal library would have (like debugging info or standard C library links) to keep the vDSO as small as possible.
  • Exported Symbols: It explicitly defines which functions (like __vdso_gettimeofday) are visible to the outside world.
  • .eh_frame_hdr placement: As we discussed, the linker script is what tells the linker: "Take all the unwinding info, build an index, and put it in a section called .eh_frame_hdr right here."