Hello,

Hope this mail finds you well. I am writing this to ask about one extension in 
GCC, which is “Conditionals with Omitted Operands”.

From the document at https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html , we 
learn that this extension could be useful in terms of avoiding the side effects 
of recomputing. However, we recently observed a case in the Linux kernel, where 
the kernel develops are using this extension but compiling their code with 
certain optimizations disabled may lead to a concurrency vulnerability. The 
general idea of this problem is, for a line of code leveraging “Conditionals 
with Omitted Operands", GCC, with fewer optimizations, could generate a 
disassembly contains two memory read to the same object. One is for checking 
the value in the first operand in the ternary expression and another is for the 
second operand, which is omitted in order to leverage this extension. Thus, 
another thread could update the object between the two read and lead to 
inconsistent behavior. We are not sure if this is a problem with GCC or the 
kernel developers should be aware of this vulnerability. Hope you could give us 
some hints.

Here I put a simple program that I hope could explain this problem.
#include<stdio.h>
#include<stdlib.h>

 unsigned int hello(int *const *a)
 {
     return (unsigned int)((unsigned int)*a & 0xFE) ? : 0x123;
 }

 int main()
 {
     int tmp;
     tmp = rand() % 10000;
     int *ptr = &tmp;
     int **pptr = &ptr;
     unsigned int result = hello(pptr);
 }

We compiled this code for two sets of GCC options and compare the disassembly 
of hello(). In option set 1, we found two memory access (option set 1:521, 
option set 1:526), thus it has the concurrency issue while in option set 2, we 
only saw on memory read(option set 2:521). We are wondering if this double 
memory read pattern is one of the side effects GCC should always avoid?


  1.
option set 1

gcc -m32 -O1 -fno-if-conversion -fno-if-conversion2 -fno-delayed-branch 
-fno-tree-fre -fno-tree-dominator-opts -fno-cprop-registers simple.c -o option1


  1.
option set 2

gcc -m32 -O1 -fno-if-conversion -fno-if-conversion2 -fno-delayed-branch 
-fno-cprop-registers simple.c -o option2


  1.
option set 1

0000051d <hello>:
 51d:   8b 44 24 04             mov    0x4(%esp),%eax
 521:   f6 00 fe                testb  $0xfe,(%eax)
 524:   74 08                   je     52e <hello+0x11>
 526:   8b 00                   mov    (%eax),%eax
 528:   25 fe 00 00 00          and    $0xfe,%eax
 52d:   c3                      ret
 52e:   b8 23 01 00 00          mov    $0x123,%eax
 533:   c3                      ret


  1.
option set 2

0000051d <hello>:
 51d:   8b 44 24 04             mov    0x4(%esp),%eax
 521:   8b 00                   mov    (%eax),%eax
 523:   25 fe 00 00 00          and    $0xfe,%eax
 528:   74 02                   je     52c <hello+0xf>
 52a:   f3 c3                   repz ret
 52c:   b8 23 01 00 00          mov    $0x123,%eax
531:   eb f7                   jmp    52a <hello+0xd>

GCC version
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 
7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs 
--enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr 
--with-gcc-major-version-only --program-suffix=-7 
--program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id 
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix 
--libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu 
--enable-libstdcxx-debug --enable-libstdcxx-time=yes 
--with-default-libstdcxx-abi=new --enable-gnu-unique-object 
--disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie 
--with-system-zlib --with-target-system-zlib --enable-objc-gc=auto 
--enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 
--with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic 
--enable-offload-targets=nvptx-none --without-cuda-driver 
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu 
--target=x86_64-linux-gnu
Thread model: posix
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)


Thanks,
Sishuai

Reply via email to