[Bug target/78631] New: [Intel MPX] libmpxwrappers shared library leads to a non-bounds-preserving memcpy()

2016-12-01 Thread dmitrii.kuvais...@tu-dresden.de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78631

Bug ID: 78631
   Summary: [Intel MPX] libmpxwrappers shared library leads to a
non-bounds-preserving memcpy()
   Product: gcc
   Version: 6.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: target
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dmitrii.kuvais...@tu-dresden.de
  Target Milestone: ---

The libc-wrappers library for Intel MPX, libmpxwrappers, has incorrect
implementations of memcpy and mempcpy functions.

When any program calls memcpy(), the compiler pass substitutes it to
__mpx_wrapper_memcpy(), so the call is redirected into libmpxwrappers.
Unfortunately, __mpx_wrapper_memcpy() has a buggy implementation which leads to
the loss of bounds information and can miss real out-of-bounds violations.

(The following was tested on gcc 6.1.0, but the code for 6.2.0 and in the
master branch seems to be the same, thus I believe this bug persists in newer
versions as well. The affected code is in libmpx/mpxwrap/mpx_wrappers.c)

So, this is the implementation of __mpx_wrapper_memcpy():

void * __mpx_wrapper_memcpy (void *dst, const void *src, size_t n) {
  return __mpx_wrapper_memmove (dst, src, n);
}

__mpx_wrapper_memmove() is:

void *__mpx_wrapper_memmove (void *dst, const void *src, size_t n) {
  ...
  __bnd_chk_ptr_bounds (dst, n);
  __bnd_chk_ptr_bounds (src, n);
  ... call real memmove() ...
}

Now, when it is compiled into a shared libmpxwrappers.so library, the following
asm results:

<__mpx_wrapper_memcpy>:
 1f50:  sub$0x8,%rsp
 1f54:  bnd callq ad0 <__mpx_wrapper_memmove@plt>
 1f5a:  add$0x8,%rsp
 1f5e:  bnd retq

<__mpx_wrapper_memmove@plt>:
 ad0:   jmpq   *0x201c5a(%rip) # 202730 <_GLOBAL_OFFSET_TABLE_+0x18>
 ad6:   pushq  $0x0
 adb:   jmpq   ac0 <_init+0x20>

<__mpx_wrapper_memmove>:
 ... actually performs bounds checking ...

Pay attention to the jmpq instruction (at line ad0) which indirectly calls
__mpx_wrapper_memmove() through PLT/GOT. Since this instruction has no BND
prefix, all BND0-3 registers will be INITed. (This of course depends on the
BNDPRESERVE bit; since BNDPRESERVE is 0 by default this is the behavior we
observed.)

In a nutshell: the PLT/GOT resolving mechanism puts a plain jmp instruction
instead of a "bnd jmp" version --> this INITs registers BND0-3 in
__mpx_wrapper_memmove() which actually performs bounds checking --> a real
out-of-bounds bug in the program is missed.

Simple workaround would be to copy-paste bounds-checking code
("__bnd_chk_ptr_bounds ...") inside __mpx_wrapper_memcpy(). Then the checks
will definitely happen before any registers are nullified.

A workaround that I used was to set BNDPRESERVE=1 (then my program bug was
correctly detected). But this worked only for my tiny program which had no
other legacy libraries.

A real solution would require re-building libmpxwrappers with a correct PLT/GOT
resolution which uses BND-prefixed jumps.

[Bug target/78631] [Intel MPX] libmpxwrappers shared library leads to a non-bounds-preserving memcpy()

2016-12-02 Thread dmitrii.kuvais...@tu-dresden.de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78631

--- Comment #2 from Dmitrii Kuvaiskii  ---
(In reply to Ilya Enkovich from comment #1)
> PLT section is generated by linker. To have MPX friendly PLT you have to
> have MPX enabled linker supporting '-z bndplt' flag and GCC should be
> configured using MPX enabled toolchain to pass this linker option it by
> default.
> Situation you describe might happen when you use old bfd or any version of
> gold.

I'm not sure I understand the answer.
If I understand right, you mean that I need to build my shared libraries using
a friendly linker which supports '-z bndplt'. This I understand, but I do not
build a shared library. My problem is that I am using the 'libmpxwrappers'
library (already built together with gcc) which I believe contains a bug
because it was built incorrectly.

Here is the test case which reproduces the problem:

#include 
#include 
char s[10];
char d[10];
__attribute__((noinline))
char* foo(char* dst, char* src, size_t size) {
return memcpy(dst, src, size);
}
int main() {
char* r = foo(d, s, 11); // out-of-bounds!
printf("r = %p\n", r);
return 0;
}

Here is how I run it:
> gcc -fcheck-pointer-bounds -mmpx test.c
> CHKP_RT_BNDPRESERVE=0 ./a.out 
r = 0x600bd8
> CHKP_RT_BNDPRESERVE=1 ./a.out 
Saw a #BR! status 1 at 0x7f17bdb84189
Saw a #BR! status 1 at 0x7f17bdb84192
r = 0x600bd8

So the obvious buffer overflow in memcpy() is detected only when I set
BNDPRESERVE=1. Debugging this with gdb, I see:

Program received signal SIGSEGV, Segmentation fault.
=> 0x779cf189 <__mpx_wrapper_memmove+89>:   bndcu  bnd0,[r15]

So the upper-bound check detected the overflow as expected.

Can you reproduce the same behavior on your machine?

(My GCC is 6.1.0, ld is bfd version 2.26.1, I see that GCC passes '-z bndplt'
to the linker and linker eats it without problems.)

[Bug target/80068] New: [Intel MPX] "internal compiler error" on 483.xalancbmk in SPEC CPU 2006

2017-03-16 Thread dmitrii.kuvais...@tu-dresden.de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80068

Bug ID: 80068
   Summary: [Intel MPX] "internal compiler error" on 483.xalancbmk
in SPEC CPU 2006
   Product: gcc
   Version: 6.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: target
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dmitrii.kuvais...@tu-dresden.de
  Target Milestone: ---

Created attachment 40985
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40985&action=edit
Preprocessed C++ file from 483.xalancbmk

The MPX pass experiences an "internal compiler error" when compiled under
g++-6.1.0 and only under `-fno-chkp-check-read`.

I run a vanilla SPEC CPU 2006 on my Ubuntu 16.04 and use GCC 6.1.0:

runspec --config intelmpx.cfg --noreportable 483.xalancbmk

This is the exact command line that fails:

-
~/bin/benchmarks/cpu2006/benchspec/CPU2006/483.xalancbmk/src$
/home/dimakuv/bin/gcc-6.1.0/install/bin/g++ -v -save-temps -DSPEC_CPU -DNDEBUG 
-DAPP_NO_THREADS -DXALAN_INMEM_MSG_LOADER -DPROJ_XMLPARSER -DPROJ_XMLUTIL
-DPROJ_PARSERS -DPROJ_SAX4C -DPROJ_SAX2 -DPROJ_DOM -DPROJ_VALIDATORS
-DXML_USE_NATIVE_TRANSCODER -DXML_USE_INMEM_MESSAGELOADER -DXML_USE_PTHREADS 
-O3 -DSPEC_CPU_LP64 -DSPEC_CPU_LINUX -fcheck-pointer-bounds -mmpx
-fno-chkp-check-read  -c DecimalDatatypeValidator.cpp -o
DecimalDatatypeValidator.o -I. -I./xercesc/dom -I./xercesc/dom/impl -I.
-I./xercesc/sax -I./xercesc/util/MsgLoaders/InMemory
-I./xercesc/util/Transcoders/Iconv -I./xalanc/include
Using built-in specs.
COLLECT_GCC=/home/dimakuv/bin/gcc-6.1.0/install/bin/g++
Target: x86_64-pc-linux-gnu
Configured with: ./configure --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 6.1.0 (GCC) 
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-D' 'SPEC_CPU' '-D' 'NDEBUG' '-D'
'APP_NO_THREADS' '-D' 'XALAN_INMEM_MSG_LOADER' '-D' 'PROJ_XMLPARSER' '-D'
'PROJ_XMLUTIL' '-D' 'PROJ_PARSERS' '-D' 'PROJ_SAX4C' '-D' 'PROJ_SAX2' '-D'
'PROJ_DOM' '-D' 'PROJ_VALIDATORS' '-D' 'XML_USE_NATIVE_TRANSCODER' '-D'
'XML_USE_INMEM_MESSAGELOADER' '-D' 'XML_USE_PTHREADS' '-O3' '-D'
'SPEC_CPU_LP64' '-D' 'SPEC_CPU_LINUX' '-fcheck-pointer-bounds' '-mmpx'
'-fno-chkp-check-read' '-c' '-o' 'DecimalDatatypeValidator.o' '-I' '.' '-I'
'./xercesc/dom' '-I' './xercesc/dom/impl' '-I' '.' '-I' './xercesc/sax' '-I'
'./xercesc/util/MsgLoaders/InMemory' '-I' './xercesc/util/Transcoders/Iconv'
'-I' './xalanc/include' '-shared-libgcc' '-mtune=generic' '-march=x86-64'

/home/dimakuv/bin/gcc-6.1.0/install/bin/../libexec/gcc/x86_64-pc-linux-gnu/6.1.0/cc1plus
-E -quiet -v -I . -I ./xercesc/dom -I ./xercesc/dom/impl -I . -I ./xercesc/sax
-I ./xercesc/util/MsgLoaders/InMemory -I ./xercesc/util/Transcoders/Iconv -I
./xalanc/include -imultiarch x86_64-linux-gnu -iprefix
/home/dimakuv/bin/gcc-6.1.0/install/bin/../lib/gcc/x86_64-pc-linux-gnu/6.1.0/
-D_GNU_SOURCE -D SPEC_CPU -D NDEBUG -D APP_NO_THREADS -D XALAN_INMEM_MSG_LOADER
-D PROJ_XMLPARSER -D PROJ_XMLUTIL -D PROJ_PARSERS -D PROJ_SAX4C -D PROJ_SAX2 -D
PROJ_DOM -D PROJ_VALIDATORS -D XML_USE_NATIVE_TRANSCODER -D
XML_USE_INMEM_MESSAGELOADER -D XML_USE_PTHREADS -D SPEC_CPU_LP64 -D
SPEC_CPU_LINUX DecimalDatatypeValidator.cpp -mmpx -mtune=generic -march=x86-64
-fcheck-pointer-bounds -fno-chkp-check-read -O3 -fpch-preprocess -o
DecimalDatatypeValidator.ii
ignoring nonexistent directory
"/home/dimakuv/bin/gcc-6.1.0/install/bin/../lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../include/c++/6.1.0"
ignoring nonexistent directory
"/home/dimakuv/bin/gcc-6.1.0/install/bin/../lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../include/c++/6.1.0/x86_64-pc-linux-gnu"
ignoring nonexistent directory
"/home/dimakuv/bin/gcc-6.1.0/install/bin/../lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../include/c++/6.1.0/backward"
ignoring nonexistent directory
"/home/dimakuv/bin/gcc-6.1.0/install/bin/../lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../x86_64-pc-linux-gnu/include"
ignoring nonexistent directory
"/home/dimakuv/bin/gcc-6.1.0/install/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../include/c++/6.1.0"
ignoring nonexistent directory
"/home/dimakuv/bin/gcc-6.1.0/install/bin/../lib/gcc/../../lib/gcc/x86_64-pc-linux-gnu/6.1.0/../../../../include/c++/6.1.0

[Bug target/80068] [Intel MPX] "internal compiler error" on 483.xalancbmk in SPEC CPU 2006

2017-03-27 Thread dmitrii.kuvais...@tu-dresden.de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80068

--- Comment #2 from Dmitrii Kuvaiskii  ---
Thanks, Martin. This patch indeed solves it.