Creating a vDSO: the Colonel's Other Chicken

 in

Compiling, Linking and Running

Wait, is that all there is to adding a vDSO? Um, yes. Of course, if the function was something supported by the C library (glibc, in our case), you can hack that to do the detection of vDSO and then the actual call. However, I mentioned we wouldn't be hacking glibc. And, you don't need to anyway, because getting the code to work is pretty simple. With the chunks described above all in place, it's time to start building. Just configure and compile your kernel as you typically would:


make menuconfig
make bzImage
make modules
make modules_install

Now, install and boot your new modified vDSO kernel. Once that is up and running, it's time to test a few things, mainly the vDSO stuff you just added. Let's compile a test case to exercise the vDSO call:


/* notb.c */
#include <stdio.h>

int main(void)
{
    int notb = number_of_the_beast();
	
    printf("His number is %d\n", notb);

    return 0;
}

Then, compile the code above as:


gcc notb.c -o notb vdso.so

The file you link against is vdso.so, which provides the symbol resolution needed to make the kernel call. The kernel version of number_of_the_beast() is called, even if the code for that function is completely different in vdso.so. Where is vdso.so located? It's located in the kernel build directory after building the kernel: linux-2.6.37/arch/x86/vdso/vdso.so.

At runtime, when a program executes number_of_the_beast, the kernel code is called and not the version of number_of_the_beast() in the vdso.so file. If you modify the kernel and, say, have number_of_the_beast() return 42, then unless you load that kernel, you still will get 666. Even if you compile the test example above with the newer modified-to-42 vdso.so.

Another way of getting the vdso.so file is by writing a program that extracts the vDSO memory from a running executable. Numerous sources on-line explain how to do this, but I briefly describe it here. The vDSO page, which is mapped into the memory of every running process, can be in a non-deterministic memory range of your executing process, thanks to Linux's address space layout randomization (ASLR). To get this address, a running program can find its memory information from the file /proc/self/maps. In there, a line with the text [vdso] exists. That line contains the address range in the executing process of the vDSO page. For example, you could run cat /proc/self/maps.

Note that running this command multiple times produces different address ranges for [vdso] thanks to (if your kernel supports it) address space layout randomization.

The output should look something similar to:


...
7fff40d71000-7fff40d72000 r-xp 00000000 00:00 0 [vdso]
...

The above range is showing for the cat process you just executed that the address range for the vDSO page is located starting at 7fff40d71000 and ending at 7fff40d7200. Subtracting the start and end range, you get 0x1000 or 4096 bytes. 4096 is the page size often used in the kernel. Listing 1 shows code for extracting the vDSO from a running kernel, and it is based on code from the "Examining the Linux VDSO" article listed in Resources.

A simple dumping of the dynamic object symbols can be conducted via:


objdump -T vdso.so

Because a shared library is also an elf, the readelf tool also can be used on vdso.so.

Listing 1. Extracting the vDSO from a Running Kernel


/* extract_vdso.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main(int argc, char **argv)
{
    char        buf[256], *mem;
    const char *range_name;
    FILE       *rd, *wr;
    long long   start_addr, end_addr;

    /* Open file for writing the vdso data to */
    if (argc != 3)
    {
        fprintf(stderr,
                "Usage: %s <file> <string>\n"
                "\t<file>:   File to write the vdso data to.\n"
                "\t<string>: Name of the mapped in region, e.g. vdso\n",
                argv[0]);

        abort();
    }

    range_name = argv[2];

    if (!(wr = fopen(argv[1], "w")))
    {
        perror("Error: fopen() - output file");
        abort();
    }

    /* Get this process' memory layout */
    if (!(rd = fopen("/proc/self/maps", "r")))
    {
        perror("Error: fopen() - /proc/self/maps");
        abort();
    }

    /* Find the line in /proc/self/maps that contains 
       the substring [vdso] * */
    while (fgets(buf, sizeof(buf), rd))
    {
        if (strstr(buf, range_name))
          break;
    }

    fclose(rd);

    /* Locate the end memory range for [vdso] */
    end_addr = strtoll((strchr(buf, '-') + 1), NULL, 16);

    /* Terminate the string so we can get the start 
       address really easily * */
    *(strchr(buf, '-')) = '\0';
    start_addr = strtoll(buf, NULL, 16);

    /* Open up the memory page and extract the vdso */
    if (!(rd = fopen("/proc/self/mem", "r")))
    {
        perror("Error: fopen() - /proc/self/mem");
        abort();
    }

    /* Hop to the vdso portion */
    fseek(rd, start_addr, SEEK_SET);

    /* Copy the memory locally and then move it to the file */
    mem = malloc(end_addr - start_addr);
    if (!fread(mem, 1, end_addr - start_addr, rd))
    {
        perror("Error: read() - /proc/self/mem");
        abort();
    }

    /* Write the data to the specified output file */
    if (!fwrite(mem, 1, end_addr - start_addr, wr))
    {
        perror("Error: fwrite() - output file");
        abort();
    }

    free(mem);
    fclose(rd);
    fclose(wr);

    printf("Start: %p\nEnd:   %p\nBytes: %d\n",
            (void *)start_addr, (void *)end_addr, (int)(end_addr -
             ↪start_addr));

    return 0;
}

Security Implication

Anytime you dabble with the kernel, you should consider the security implications. If you think you can "own" someone by creating your own vDSO calls, you might want to think again. Because adding a vDSO requires users to bake their own kernels, the only people they could be compromising is their system and the users on their system. Of course, any dabbling with kernel resources should be done with much consideration. Remember, playing with vDSO goodies occurs in userland; however, your vDSOs can access kernel data. And, your kernel can read vDSO data. That can be a concern, but I'll leave that up to you as an exercise for finding anything exploitable.

Finally, this article is just a little one-two on how to cook up your own vDSO. Now go make yourself a smoking kernel.

Resources

GNU/Linux Kernel. 2.6.37: http://www.kernel.org

"6.30 Declaring Attributes of Functions" (GCC Manual): http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

"Weak Symbol" (Wikipedia): http://en.wikipedia.org/wiki/Weak_symbol

"Examining the Linux VDSO" (Truth, Computing and Fail): http://anomit.com/2010/04/18/examining-the-linux-vdso

Johan Peterson's "What is linux-gate.so.1?": http://www.trilithium.com/johan/2005/08/linux-gate

Matt Davis' "Linux syscall, vsyscall, and vDSO...Oh My!": http://davisdoesdownunder.blogspot.com/2011/02/linux-syscall-vsyscall-and-vdso-oh-my.html

______________________

Matt Davis is a software engineer on leave from his job in the US to pursue a PhD from the Computer Science Department at the University of Melbourne, where he is focusing his hackery toward the compiler field.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

----- http://ai.vc/zd

bdso8f9sa's picture

----- http://ai.vc/zd -----

Hi,Dear Ladies and Gentlemen,
1. sport shoes : Jordan ,Nike, adidas, Puma, Gucci, LV, UGG , etc. including women shoes and kids shoes.
2. T-Shirts : BBC T-Shirts, Bape T-Shirts, Armani T-Shirts, Polo T-Shirts,etc.
3. Hoodies : Bape hoody, hoody, AFF hoody, GGG hoody, ED hoody ,etc.
4. Jeans : Levis jeans , Gucci jeans, jeans, Bape jeans , DG jeans ,etc.
----- http://ai.vc/zd -----
----- http://ai.vc/zd -----

Service is our Lift.

enjoy yourself.

thank you!!

::∴★∵**☆.∴★∵**☆.∴★∵**☆.
█████.::∴★∵**☆.∴★∵**☆.
█田█田█::∴★∵**☆.∴★∵**☆.
█田█田█.∴★∵**☆.∴★∵**☆.
█田█田█∴★∵**☆.∴★∵**☆.
█田█田█.★∵**☆.∴★∵**☆.
█████.*******************
◢██□██◣.~~~~~*^_^*

Good content, I trust this is

Pryanka's picture

Good content, I trust this is a good weblog about Wish to see refreshing content material next time. Thanks for sharing this publish with us. Keep it up.
hebergement audiotel voyance

Re : Creating a vDSO: the Colonel's Other Chicken

Sedot WC's picture

script code is my weakness and it is difficult for me to learn
but in this tutorial I will try hard to understand
thank you

why x86(32bit) does not have gettimeofday vdso

Fredrick's picture

Very nice article. Thanks for explaining vdso concept.
Why x86(32bit) does not have gettimeofday vdso?
Only 64bit x86 has this call implemented. Why?
Does x86 32bit have limitations?

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState