All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
@ 2011-06-01 11:42 Cédric VINCENT
  2011-06-01 13:26 ` Richard Henderson
  0 siblings, 1 reply; 9+ messages in thread
From: Cédric VINCENT @ 2011-06-01 11:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent ALFONSI, Cédric VINCENT, Riku Voipio

From: Laurent ALFONSI <laurent.alfonsi@st.com>

The dynamic linker of the GNU C library v2.10+ uses the ELF auxialiary
vector AT_RANDOM as a pointer to a 16-bit random value.  Prior this
patch the value of AT_RANDOM was not defined by the ELF loader of QEMU
so the GNU dynamic linker de-referenced the NULL pointer instead.  As
a consequence any target program linked to the GNU C library v2.10+
crashed due to a SEGFAULT.

Note AT_RANDOM now points to the start of the text segment thus the
16-bit value is not random at all, however it is definitively
readable.  This "dummy" behavior could be improved later.

Signed-off-by: Laurent ALFONSI <laurent.alfonsi@st.com>
Signed-off-by: Cédric VINCENT <cedric.vincent@st.com>
---

You can easily test this patch with ARMedSlack-13+:

    ftp://ftp.armedslack.org/armedslack/armedslack-devtools/minirootfs/roots/

 linux-user/elfload.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index dcfeb7a..6f67286 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -927,7 +927,7 @@ struct exec
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
 #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
 
-#define DLINFO_ITEMS 12
+#define DLINFO_ITEMS 13
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
@@ -1271,6 +1271,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+
+    /* The dynamic linker of the GNU C library v2.10+ uses the ELF
+     * auxialiary vector AT_RANDOM as a pointer to a 16-bit random
+     * value.  Note the start of the text segment is not random at
+     * all, however it is definitively readeable. */
+    NEW_AUX_ENT(AT_RANDOM, (abi_ulong) info->start_code);
+
     if (k_platform)
         NEW_AUX_ENT(AT_PLATFORM, u_platform);
 #ifdef ARCH_DLINFO
-- 
1.7.5.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
  2011-06-01 11:42 [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR Cédric VINCENT
@ 2011-06-01 13:26 ` Richard Henderson
  2011-06-01 13:47   ` cedric.vincent
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Henderson @ 2011-06-01 13:26 UTC (permalink / raw)
  To: Cédric VINCENT; +Cc: Laurent ALFONSI, Riku Voipio, qemu-devel

On 06/01/2011 04:42 AM, Cédric VINCENT wrote:
> +    /* The dynamic linker of the GNU C library v2.10+ uses the ELF
> +     * auxialiary vector AT_RANDOM as a pointer to a 16-bit random
> +     * value.  Note the start of the text segment is not random at
> +     * all, however it is definitively readeable. */
> +    NEW_AUX_ENT(AT_RANDOM, (abi_ulong) info->start_code);

16 bytes, not 16 bits.  Typos for auxiliary and readable.


r~

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
  2011-06-01 13:26 ` Richard Henderson
@ 2011-06-01 13:47   ` cedric.vincent
  2011-06-01 14:35     ` [Qemu-devel] [PATCH v2] " Cédric VINCENT
  2011-06-01 15:33     ` [Qemu-devel] [PATCH] " Richard Henderson
  0 siblings, 2 replies; 9+ messages in thread
From: cedric.vincent @ 2011-06-01 13:47 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Laurent ALFONSI, Riku Voipio, qemu-devel

On Wed, Jun 01, 2011 at 03:26:09PM +0200, Richard Henderson wrote:
> 
> 16 bytes, not 16 bits.

You're right it's not 16 bits, it's "sizeof(uintptr_t)" actually:

    http://repo.or.cz/w/glibc.git/blob/glibc-2.10:/sysdeps/unix/sysv/linux/dl-osinfo.h#l89

>  Typos for auxiliary and readable.

Thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH v2] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
  2011-06-01 13:47   ` cedric.vincent
@ 2011-06-01 14:35     ` Cédric VINCENT
  2011-06-01 15:33     ` [Qemu-devel] [PATCH] " Richard Henderson
  1 sibling, 0 replies; 9+ messages in thread
From: Cédric VINCENT @ 2011-06-01 14:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent ALFONSI, Cédric VINCENT, Riku Voipio, Richard Henderson

From: Laurent ALFONSI <laurent.alfonsi@st.com>

The dynamic linker of the GNU C library v2.10+ uses the ELF auxialiary
vector AT_RANDOM as a pointer to a word with random value.  Prior this
patch the value of AT_RANDOM was not defined by the ELF loader of QEMU
so the GNU dynamic linker de-referenced the NULL pointer instead.  As
a consequence any target program linked to the GNU C library v2.10+
crashed due to a SEGFAULT.

Note AT_RANDOM now points to the start of the text segment thus the
value is not random at all, however it is definitively readable.  This
"dummy" behavior could be improved later.

Signed-off-by: Laurent ALFONSI <laurent.alfonsi@st.com>
Signed-off-by: Cédric VINCENT <cedric.vincent@st.com>
---
 linux-user/elfload.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index dcfeb7a..111128c 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -927,7 +927,7 @@ struct exec
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
 #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
 
-#define DLINFO_ITEMS 12
+#define DLINFO_ITEMS 13
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
@@ -1271,6 +1271,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+
+    /* The dynamic linker of the GNU C library v2.10+ uses the ELF
+     * auxiliary vector AT_RANDOM as a pointer to a word with random
+     * value.  Note the start of the text segment is not random at
+     * all, however it is definitively readable.  */
+    NEW_AUX_ENT(AT_RANDOM, (abi_ulong) info->start_code);
+
     if (k_platform)
         NEW_AUX_ENT(AT_PLATFORM, u_platform);
 #ifdef ARCH_DLINFO
-- 
1.7.5.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
  2011-06-01 13:47   ` cedric.vincent
  2011-06-01 14:35     ` [Qemu-devel] [PATCH v2] " Cédric VINCENT
@ 2011-06-01 15:33     ` Richard Henderson
  2011-06-03  6:46       ` cedric.vincent
  2011-06-20  6:43       ` [Qemu-devel] [PATCH v3] linux-user: Define AT_RANDOM to support target stack protection mechanism Cédric VINCENT
  1 sibling, 2 replies; 9+ messages in thread
From: Richard Henderson @ 2011-06-01 15:33 UTC (permalink / raw)
  To: cedric.vincent, qemu-devel, Laurent ALFONSI, Riku Voipio

On 06/01/2011 06:47 AM, cedric.vincent@st.com wrote:
> On Wed, Jun 01, 2011 at 03:26:09PM +0200, Richard Henderson wrote:
>>
>> 16 bytes, not 16 bits.
> 
> You're right it's not 16 bits, it's "sizeof(uintptr_t)" actually:

No, it's not.

        unsigned char k_rand_bytes[16];
        elf_addr_t __user *u_rand_bytes;
...
        /*
         * Generate 16 random bytes for userspace PRNG seeding.
         */
        get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
        u_rand_bytes = (elf_addr_t __user *)
                       STACK_ALLOC(p, sizeof(k_rand_bytes));
        if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
                return -EFAULT;
...
        NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes);


Frankly, it's trivial to do this right in create_elf_tables.
Grab 16 bytes at SP right at the beginning of the function,
fill it with whatever random values seem good.

I suggest at minimum a command-line argument to force a 
particular AT_RANDOM value, for repeatability.


r~

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
  2011-06-01 15:33     ` [Qemu-devel] [PATCH] " Richard Henderson
@ 2011-06-03  6:46       ` cedric.vincent
  2011-06-13 12:03         ` Laurent Alfonsi
  2011-06-20  6:43       ` [Qemu-devel] [PATCH v3] linux-user: Define AT_RANDOM to support target stack protection mechanism Cédric VINCENT
  1 sibling, 1 reply; 9+ messages in thread
From: cedric.vincent @ 2011-06-03  6:46 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Laurent ALFONSI, Riku Voipio, qemu-devel

On Wed, Jun 01, 2011 at 05:33:55PM +0200, Richard Henderson wrote:
> On 06/01/2011 06:47 AM, cedric.vincent@st.com wrote:
> > On Wed, Jun 01, 2011 at 03:26:09PM +0200, Richard Henderson wrote:
> >>
> >> 16 bytes, not 16 bits.
> > 
> > You're right it's not 16 bits, it's "sizeof(uintptr_t)" actually:
> 
> No, it's not.
> 
>         unsigned char k_rand_bytes[16];
>         elf_addr_t __user *u_rand_bytes;
> ...
>         /*
>          * Generate 16 random bytes for userspace PRNG seeding.
>          */
>         get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
>         u_rand_bytes = (elf_addr_t __user *)
>                        STACK_ALLOC(p, sizeof(k_rand_bytes));
>         if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
>                 return -EFAULT;
> ...
>         NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes);

It's clearer to me now, thanks.


> Frankly, it's trivial to do this right in create_elf_tables.
> Grab 16 bytes at SP right at the beginning of the function,
> fill it with whatever random values seem good.
> 
> I suggest at minimum a command-line argument to force a 
> particular AT_RANDOM value, for repeatability.

OK, I will submit you such a patch soon.

Thanks,
Cédric.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
  2011-06-03  6:46       ` cedric.vincent
@ 2011-06-13 12:03         ` Laurent Alfonsi
  2011-06-13 15:53           ` Richard Henderson
  0 siblings, 1 reply; 9+ messages in thread
From: Laurent Alfonsi @ 2011-06-13 12:03 UTC (permalink / raw)
  To: Cedric VINCENT; +Cc: Riku Voipio, qemu-devel, Richard Henderson

>>          unsigned char k_rand_bytes[16];
>>          elf_addr_t __user *u_rand_bytes;
>> ...
>>          /*
>>           * Generate 16 random bytes for userspace PRNG seeding.
>>           */
>>          get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes));
>>          u_rand_bytes = (elf_addr_t __user *)
>>                         STACK_ALLOC(p, sizeof(k_rand_bytes));
>>          if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes)))
>>                  return -EFAULT;
>> ...
>>          NEW_AUX_ENT(AT_RANDOM, (elf_addr_t)(unsigned long)u_rand_bytes);
> It's clearer to me now, thanks.
It is fine with me, I also understand better now.
And this now brings me to another point : In that case, it might have 
sense to also add the auxv AT_RANDOM_SIZE.
     http://sources.redhat.com/ml/libc-alpha/2008-10/msg00016.html

>> I suggest at minimum a command-line argument to force a
>> particular AT_RANDOM value, for repeatability.
Yep, I agree.

Laurent.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR
  2011-06-13 12:03         ` Laurent Alfonsi
@ 2011-06-13 15:53           ` Richard Henderson
  0 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2011-06-13 15:53 UTC (permalink / raw)
  To: Laurent Alfonsi; +Cc: Cedric VINCENT, Riku Voipio, qemu-devel

On 06/13/2011 05:03 AM, Laurent Alfonsi wrote:
> And this now brings me to another point : In that case, it might have
> sense to also add the auxv AT_RANDOM_SIZE.
>     http://sources.redhat.com/ml/libc-alpha/2008-10/msg00016.html

That never made it into the upstream kernel though.


r~

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH v3] linux-user: Define AT_RANDOM to support target stack protection mechanism.
  2011-06-01 15:33     ` [Qemu-devel] [PATCH] " Richard Henderson
  2011-06-03  6:46       ` cedric.vincent
@ 2011-06-20  6:43       ` Cédric VINCENT
  1 sibling, 0 replies; 9+ messages in thread
From: Cédric VINCENT @ 2011-06-20  6:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent ALFONSI, Cédric VINCENT, Riku Voipio, Richard Henderson

From: Laurent ALFONSI <laurent.alfonsi@st.com>

Note that the support for the command-line argument requires:

     1. add the new field "uint8_t rand_bytes[16]" to "struct
        image_info" since only the variable "info" lives both in
        main() and in create_elf_tables()

     2. write a dedicated parser to convert the command-line to fill
        rand_bytes[]

These two steps aren't really hard to achieve but I finally think they
are a little bit overkill regarding the purpose of these 16 bytes.
Maybe we could always fill the 16 bytes pointed to by AT_RANDOM with
zero if we really want to get reproducibility.

Regards,
Cédric.

8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----

The dynamic linker from the GNU C library v2.10+ uses the ELF
auxiliary vector AT_RANDOM [1] as a pointer to 16 bytes with random
values to initialize the stack protection mechanism.  Technically the
emulated GNU dynamic linker crashes due to a NULL pointer
derefencement if it is built with stack protection enabled and if
AT_RANDOM is not defined by the QEMU ELF loader.

[1] This ELF auxiliary vector was introduced in Linux v2.6.29.

This patch can be tested with the code above:

    #include <elf.h>       /* Elf*_auxv_t, AT_RANDOM, */
    #include <stdio.h>     /* printf(3), */
    #include <stdlib.h>    /* exit(3), EXIT_*, */
    #include <stdint.h>    /* uint8_t, */
    #include <string.h>    /* memcpy(3), */

    #if defined(__LP64__) || defined(__ILP64__) || defined(__LLP64__)
    #    define Elf_auxv_t Elf64_auxv_t
    #else
    #    define Elf_auxv_t Elf32_auxv_t
    #endif

    main(int argc, char* argv[], char* envp[])
    {
        Elf_auxv_t *auxv;

        /* *envp = NULL marks end of envp. */
        while (*envp++ != NULL);

        /* auxv->a_type = AT_NULL marks the end of auxv. */
        for (auxv = (Elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
            if (auxv->a_type == AT_RANDOM) {
                int i;
                uint8_t rand_bytes[16];

                printf("AT_RANDOM is: 0x%x\n", auxv->a_un.a_val);
                memcpy(rand_bytes, (const uint8_t *)auxv->a_un.a_val, sizeof(rand_bytes));
                printf("it points to: ");
                for (i = 0; i < 16; i++) {
                    printf("0x%02x ", rand_bytes[i]);
                }
                printf("\n");
                exit(EXIT_SUCCESS);
            }
        }
        exit(EXIT_FAILURE);
    }

Changes introduced in v2 and v3:

    * Fix typos + thinko (AT_RANDOM is used for stack canary, not for
      ASLR)

    * AT_RANDOM points to 16 random bytes stored inside the user
      stack.

    * Add a small test program.

Signed-off-by: Cédric VINCENT <cedric.vincent@st.com>
Signed-off-by: Laurent ALFONSI <laurent.alfonsi@st.com>
---
 linux-user/elfload.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index dcfeb7a..23c69d9 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -927,7 +927,7 @@ struct exec
 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
 #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
 
-#define DLINFO_ITEMS 12
+#define DLINFO_ITEMS 13
 
 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
@@ -1202,6 +1202,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
 {
     abi_ulong sp;
     int size;
+    int i;
+    abi_ulong u_rand_bytes;
+    uint8_t k_rand_bytes[16];
     abi_ulong u_platform;
     const char *k_platform;
     const int n = sizeof(elf_addr_t);
@@ -1231,6 +1234,20 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
         /* FIXME - check return value of memcpy_to_target() for failure */
         memcpy_to_target(sp, k_platform, len);
     }
+
+    /*
+     * Generate 16 random bytes for userspace PRNG seeding (not
+     * cryptically secure but it's not the aim of QEMU).
+     */
+    srand((unsigned int) time(NULL));
+    for (i = 0; i < 16; i++) {
+        k_rand_bytes[i] = rand();
+    }
+    sp -= 16;
+    u_rand_bytes = sp;
+    /* FIXME - check return value of memcpy_to_target() for failure */
+    memcpy_to_target(sp, k_rand_bytes, 16);
+
     /*
      * Force 16 byte _final_ alignment here for generality.
      */
@@ -1271,6 +1288,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
+    NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
+
     if (k_platform)
         NEW_AUX_ENT(AT_PLATFORM, u_platform);
 #ifdef ARCH_DLINFO
-- 
1.7.5.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-06-20  6:46 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-01 11:42 [Qemu-devel] [PATCH] linux-user: Define AT_RANDOM to support target dynamic linkers that do ASLR Cédric VINCENT
2011-06-01 13:26 ` Richard Henderson
2011-06-01 13:47   ` cedric.vincent
2011-06-01 14:35     ` [Qemu-devel] [PATCH v2] " Cédric VINCENT
2011-06-01 15:33     ` [Qemu-devel] [PATCH] " Richard Henderson
2011-06-03  6:46       ` cedric.vincent
2011-06-13 12:03         ` Laurent Alfonsi
2011-06-13 15:53           ` Richard Henderson
2011-06-20  6:43       ` [Qemu-devel] [PATCH v3] linux-user: Define AT_RANDOM to support target stack protection mechanism Cédric VINCENT

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.