RFC: GCC plugin to find encrypted function pointer calls in glibc

Aldy Hernandez aldyh@redhat.com
Mon May 2 12:02:00 GMT 2016


On 04/29/2016 09:21 PM, Carlos O'Donell wrote:

> You can build glibc with gcc 4.7 or newer.
>
> (1) static inline wrapper with function attribute:
>
> For a representative set of architectures, say x86_64, i686, ppc64,
> s390x, aarch64, and arm, does a 4.7 or newer compiler do as good a
> job with a static inline function as it does with the macro that
> evaluates to a bare assembly?

I grabbed the relevant bits from various glibc backends (x86_64, ppc64, 
and arm) and made a testcase that would work on all three architectures. 
  All we need to verify is that the code generated for 
using_original_macro_demangler() and using_new_inline_demangler() is 
exactly the same for all three architectures.  I have visually verified 
that this is so.

It looks like all other architectures are variants of the same pattern 
(inline asm or some boiler plate code looking at a global that may be in 
a TLS variable), so I didn't bother.

As you can see, what I propose is something as simple as:

#define OLD_MACRO_PTR_DEMANGLE(var) asm("magic")

static inline uintptr_t
new_ptr_demangle (uintptr_t var)
{
   OLD_MACRO_PTR_DEMANGLE (var);
   return var;
}

#define PTR_DEMANGLE(var) \
   var = (typeof(var)) new_ptr_demangle ((uintptr_t) var)

Do y'all agree?  Can we use inline functions wrapping the asm's and tag 
an attribute on the function?

Aldy


/* Testcase to compare pointer demangling code on various
    architectures.  */

typedef struct
{
   int blah1;
   int blah2;
   unsigned int pointer_guard;
   int blah3;
} tcbhead_t;

#ifdef __x86_64__
typedef unsigned long long int uintptr_t;
#define LP_SIZE "8"
#  define PTR_DEMANGLE(var)	asm ("ror $2*" LP_SIZE "+1, %0\n"	\
				     "xor %%fs:%c2, %0"			\
				     : "=r" (var)			\
				     : "0" (var),			\
				       "i" (__builtin_offsetof (tcbhead_t,    \
						      pointer_guard)))
#elif defined __powerpc64__
typedef unsigned long long int uintptr_t;
register void *__thread_register __asm__ ("r13");
# define TLS_TCB_OFFSET 0x7000
# define THREAD_GET_POINTER_GUARD() \
     (((tcbhead_t *) ((char *) __thread_register 
        \
                      - TLS_TCB_OFFSET))[-1].pointer_guard)
#  define PTR_MANGLE(var) \
   (var) = (__typeof (var)) ((uintptr_t) (var) ^ 
THREAD_GET_POINTER_GUARD ())
#  define PTR_DEMANGLE(var)	PTR_MANGLE (var)

#elif defined __arm__
typedef unsigned long int uintptr_t;
# define attribute_hidden __attribute__ ((visibility ("hidden")))
#define attribute_relro __attribute__ ((section (".data.rel.ro")))
/* Only exported for architectures that don't store the pointer guard
    value in thread local area.  */
uintptr_t __pointer_chk_guard
         attribute_relro attribute_hidden __attribute__ ((nocommon));
#  define PTR_MANGLE(var) \
   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
#else
#error "architecture not supported"
#endif

static inline uintptr_t
ptr_demangle (uintptr_t var)
{
   PTR_DEMANGLE (var);
   return var;
}

#define PTR_DEMANGLE2(var) \
   var = (typeof(var)) ptr_demangle ((uintptr_t) var)

typedef int (*callback) (void);

void
using_original_macro_demangler (callback cb)
{
   PTR_DEMANGLE (cb);
   cb();
}

void
using_new_inline_demangler (callback cb)
{
   PTR_DEMANGLE2 (cb);
   cb();
}



More information about the Libc-alpha mailing list