public inbox for libc-ports@sourceware.org
 help / color / mirror / Atom feed
From: Venkataramanan Kumar <venkataramanan.kumar@linaro.org>
To: libc-ports@sourceware.org,
	Marcus Shawcroft <marcus.shawcroft@arm.com>,
		Marcus Shawcroft <marcus.shawcroft@gmail.com>,
	Patch Tracking <patch@linaro.org>
Subject: [RFC] [PATCH] [Aarch64] : Stack guard support in glibc
Date: Mon, 26 Aug 2013 04:15:00 -0000	[thread overview]
Message-ID: <CAJK_mQ2V=Q4K-wRyOYaPcvD-QhkkAdtMEUrE+pN3NzBJh1d8dw@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2447 bytes --]

Hi Maintainers,

Attached is RFC patch that adds stack guard support in glibc for
Aarch64 for review.

The TCB is 16 bytes in Aarch64 and tp points to the dtvt. Before the
TCB, the pthread structure is placed. This patch places the stack
guard (SG) and pointer gaurd variable (PG) between the TCB and pthread
structures.

We can access thread pointer using "msr" instruction, the compiler
will generate the following assembly to access the stack guard placed
before the TCB .

msr tpidr_el0, x0
ldr x1, [x0-8]


                       tp
                        |
 pthread            v
 -----------------------------
|         |PG|SG| dtvt|  |
 ------------------------------
                       TCB


I did a quick check by building eglibc and moving the built runtime
linker ld-linux-aarch64.so,1 and libc "libc.so.2.17.90" to the V8
model running open embedded image.

And ran the following test case using "ld-linux-aarch64.so.1 --library
./libc.so test.out 1" where libc.so points to newly built one.

---test.c---
#include <string.h>
#include <stdio.h>

void test_stack_smashing(int corrupt)
{
    long stack_val,temp;

    char arr[5];
    char * ptr = arr;

    if (!corrupt)

    {
        strcpy( ptr,"abcd");
        printf("copied string is %s\n",ptr);
    }
    else
    {

        printf("overflowing the buffer and hitting the canary now\n");
            memset (ptr,0,12);
        printf("Overwritten the buffer\n" );

              asm("mrs %0, tpidr_el0\n" "ldr %1, [%0,-8]\n" : "=r"
(stack_val) : "r" (temp));
        printf(" Canary value is %x\n", stack_val);

    }

}

int main(char *argc, char *argv[])
{

    if (0 == strcmp(argv[1],"0"))
    {
        test_stack_smashing(0);
        printf("Passed Canary test\n");
    }
    else
    {
        test_stack_smashing(1);
        printf("Failed Canary test\n");
    }
    return 0;
}

And without patch I got:

(Snip)
overflowing the buffer and hitting the canary now
Overwritten the buffer
 Canary value is 0
Failed Canary test
(Snip)

Canary value is zero and this happens without my change because I
believe there is already space between TCB and pthread nodes due to
alignment enforcement.

With the path:

(Snip)
overflowing the buffer and hitting the canary now
Overwritten the buffer
 Canary value is 9900cf00
*** stack smashing detected ***: ./a.out terminated
Aborted
(Snip)

I also checked the canary value and keeps changing from run to run.

regards,
Venkat.

[-- Attachment #2: glibc.tls.stack.guard.aarch64.diff --]
[-- Type: application/octet-stream, Size: 2151 bytes --]

Index: tls.h
===================================================================
--- tls.h	(revision 23742)
+++ tls.h	(working copy)
@@ -68,10 +68,15 @@
 # define TLS_TCB_SIZE		sizeof (tcbhead_t)
 
 /* This is the size we need before TCB.  */
-# define TLS_PRE_TCB_SIZE	sizeof (struct pthread)
+# define TLS_PRE_TCB_SIZE \
+  (sizeof (struct pthread)                                              \
+   + (PTHREAD_STRUCT_END_PADDING < 2 * sizeof (uintptr_t)               \
+      ? ((2 * sizeof (uintptr_t) + __alignof__ (struct pthread) - 1)    \
+         & ~(__alignof__ (struct pthread) - 1))                         \
+      : 0))
 
 /* Alignment requirements for the TCB.  */
-# define TLS_TCB_ALIGN		__alignof__ (tcbhead_t)
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
 
 /* Install the dtv pointer.  The pointer passed is to the element with
    index -1 which contain the length.  */
@@ -98,12 +103,28 @@
 
 /* Return the thread descriptor for the current thread.  */
 # define THREAD_SELF \
- ((struct pthread *)__builtin_thread_pointer () - 1)
+ ((struct pthread *)((char *) __builtin_thread_pointer () - TLS_PRE_TCB_SIZE))
 
 /* Magic for libthread_db to know how to do THREAD_SELF.  */
 # define DB_THREAD_SELF \
-  CONST_THREAD_AREA (64, sizeof (struct pthread))
+  CONST_THREAD_AREA (64, TLS_PRE_TCB_SIZE)
 
+/* Set the stack guard field in TCB head.  */
+#define THREAD_SET_STACK_GUARD(value) \
+  (((uintptr_t *) __builtin_thread_pointer ())[-1] = (value))
+#define THREAD_COPY_STACK_GUARD(descr) \
+  (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-1] \
+   = ((uintptr_t *) __builtin_thread_pointer ())[-1])
+
+/* Set the pointer guard field in TCB head.  */
+#define THREAD_GET_POINTER_GUARD() \
+  (((uintptr_t *) __builtin_thread_pointer ())[-2])
+#define THREAD_SET_POINTER_GUARD(value) \
+  (((uintptr_t *) __builtin_thread_pointer ())[-2] = (value))
+#define THREAD_COPY_POINTER_GUARD(descr) \
+  (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-2] \
+   = THREAD_GET_POINTER_GUARD ())
+
 /* Access to data in the thread descriptor is easy.  */
 # define THREAD_GETMEM(descr, member) \
   descr->member

             reply	other threads:[~2013-08-26  4:15 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-26  4:15 Venkataramanan Kumar [this message]
2013-08-28  2:13 ` Carlos O'Donell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAJK_mQ2V=Q4K-wRyOYaPcvD-QhkkAdtMEUrE+pN3NzBJh1d8dw@mail.gmail.com' \
    --to=venkataramanan.kumar@linaro.org \
    --cc=libc-ports@sourceware.org \
    --cc=marcus.shawcroft@arm.com \
    --cc=marcus.shawcroft@gmail.com \
    --cc=patch@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).