lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 30 Nov 2017 13:22:57 -0600
From:   Dennis Zhou <dennisszhou@...il.com>
To:     Kees Cook <keescook@...omium.org>
Cc:     Dmitry Vyukov <dvyukov@...gle.com>,
        Fengguang Wu <fengguang.wu@...el.com>,
        Ard Biesheuvel <ard.biesheuvel@...aro.org>,
        Linux-MM <linux-mm@...ck.org>, Tejun Heo <tj@...nel.org>,
        Christoph Lameter <cl@...ux.com>,
        Linus Torvalds <torvalds@...ux-foundation.org>,
        Josef Bacik <jbacik@...com>,
        LKML <linux-kernel@...r.kernel.org>, LKP <lkp@...org>,
        Andrey Ryabinin <aryabinin@...tuozzo.com>,
        Mark Rutland <mark.rutland@....com>
Subject: Re: [pcpu] BUG: KASAN: use-after-scope in
 pcpu_setup_first_chunk+0x1e3b/0x29e2

Hi Dmitry and Kees,

On Thu, Nov 30, 2017 at 10:10:41AM -0800, Kees Cook wrote:
> > Are we sure that structleak plugin is not at fault? If yes, then we
> > need to report this to https://gcc.gnu.org/bugzilla/ with instructions
> > on how to build/use the plugin.

I believe this is an issue with the structleak plugin and not gcc. The
bug does not show up if you compile without
GCC_PLUGIN_STRUCTLEAK_BYREF_ALL.

It seems to be caused by the initializer not respecting the ASAN_MARK
calls. Therefore, if an inlined function gets called from a for loop,
the initializer code gets invoked bugging in the second iteration. Below
is the tree dump for the structleak plugin from the reproducer in the
previous email. In bb 2 of INIT_LIST_HEAD, the __u = {} is before the
unpoison call. This is inlined in bb 3 of main.

> 
> I thought from earlier in this thread that the bug just changed
> locations depending on the plugin. Does the issue still exist with the
> plugin disabled?
> 

The bug changing locations was me just verifying it was not an issue
with percpu memory. I manually unrolled the for loop to show that the
percpu bug disappears, but manifests later on. The issue does not exist
with the BY_REF_ALL config.

Thanks,
Dennis

----

;; Function __write_once_size (__write_once_size, funcdef_no=2, decl_uid=3117, cgraph_uid=2, symbol_order=2)

__attribute__((always_inline))
__write_once_size (volatile void * p, void * res, int size)
{
  unsigned char _1;
  short unsigned int _2;
  unsigned int _3;
  long unsigned int _4;
  long unsigned int _5;

  <bb 2> [0.00%]:
  switch (size_7(D)) <default: <L4> [0.00%], case 1: <L0> [0.00%], case 2: <L1> [0.00%], case 4: <L2> [0.00%], case 8: <L3> [0.00%]>

<L0> [0.00%]:
  _1 = MEM[(__u8 *)res_9(D)];
  MEM[(volatile __u8 *)p_10(D)] ={v} _1;
  goto <bb 8>; [0.00%]

<L1> [0.00%]:
  _2 = MEM[(__u16 *)res_9(D)];
  MEM[(volatile __u16 *)p_10(D)] ={v} _2;
  goto <bb 8>; [0.00%]

<L2> [0.00%]:
  _3 = MEM[(__u32 *)res_9(D)];
  MEM[(volatile __u32 *)p_10(D)] ={v} _3;
  goto <bb 8>; [0.00%]

<L3> [0.00%]:
  _4 = MEM[(__u64 *)res_9(D)];
  MEM[(volatile __u64 *)p_10(D)] ={v} _4;
  goto <bb 8>; [0.00%]

<L4> [0.00%]:
  _5 = (long unsigned int) size_7(D);
  __builtin_memcpy (p_10(D), res_9(D), _5);

  <bb 8> [0.00%]:
  return;

}



;; Function INIT_LIST_HEAD (INIT_LIST_HEAD, funcdef_no=3, decl_uid=3129, cgraph_uid=3, symbol_order=3)


Symbols to be put in SSA form
{ D.3149 }
Incremental SSA update started at block: 0
Number of blocks in CFG: 9
Number of blocks to update: 8 ( 89%)


__attribute__((always_inline))
INIT_LIST_HEAD (struct list_head * list)
{
  volatile void * p;
  void * res;
  int size;
  union 
  {
    struct list_head * __val;
    char __c[1];
  } __u;
  struct list_head * D.3135;
  struct list_head * * _1;
  struct list_head * _7;
  unsigned char _13;
  short unsigned int _14;
  unsigned int _15;
  long unsigned int _16;
  long unsigned int _17;

  <bb 2> [0.00%]:
  __u = {};
  ASAN_MARK (UNPOISON, &__u, 8);
  __u.__val = list_4(D);
  _1 = &list_4(D)->next;
  p_10 = _1;
  res_11 = &__u.__c;
  size_12 = 8;
  switch (size_12) <default: <L4> [0.00%], case 1: <L0> [0.00%], case 2: <L1> [0.00%], case 4: <L2> [0.00%], case 8: <L3> [0.00%]>

<L0> [0.00%]:
  _13 = MEM[(__u8 *)res_11];
  MEM[(volatile __u8 *)p_10] ={v} _13;
  goto <bb 8>; [0.00%]

<L1> [0.00%]:
  _14 = MEM[(__u16 *)res_11];
  MEM[(volatile __u16 *)p_10] ={v} _14;
  goto <bb 8>; [0.00%]

<L2> [0.00%]:
  _15 = MEM[(__u32 *)res_11];
  MEM[(volatile __u32 *)p_10] ={v} _15;
  goto <bb 8>; [0.00%]

<L3> [0.00%]:
  _16 = MEM[(__u64 *)res_11];
  MEM[(volatile __u64 *)p_10] ={v} _16;
  goto <bb 8>; [0.00%]

<L4> [0.00%]:
  _17 = (long unsigned int) size_12;
  __builtin_memcpy (p_10, res_11, _17);

  <bb 8> [0.00%]:
  _7 = __u.__val;
  ASAN_MARK (POISON, &__u, 8);
  list_4(D)->prev = list_4(D);
  return;

}



;; Function main (main, funcdef_no=4, decl_uid=3138, cgraph_uid=4, symbol_order=4)


Symbols to be put in SSA form
{ D.3150 }
Incremental SSA update started at block: 0
Number of blocks in CFG: 13
Number of blocks to update: 12 ( 92%)


main (int argc, char * * argv)
{
  struct list_head * D.3165;
  union 
  {
    struct list_head * __val;
    char __c[1];
  } __u;
  int size;
  void * res;
  volatile void * p;
  struct list_head * list;
  int i;
  struct list_head * p;
  int D.3146;
  long unsigned int _1;
  long unsigned int _2;
  struct list_head * _3;
  int _11;
  struct list_head * * _15;
  unsigned char _19;
  short unsigned int _20;
  unsigned int _21;
  long unsigned int _22;
  long unsigned int _23;
  struct list_head * _24;

  <bb 2> [0.00%]:
  __u = {};
  p_8 = malloc (160);
  i_9 = 0;
  goto <bb 10>; [0.00%]

  <bb 3> [0.00%]:
  _1 = (long unsigned int) i_4;
  _2 = _1 * 16;
  _3 = p_8 + _2;
  list_14 = _3;
  __u = {};
  ASAN_MARK (UNPOISON, &__u, 8);
  __u.__val = list_14;
  _15 = &list_14->next;
  p_16 = _15;
  res_17 = &__u.__c;
  size_18 = 8;
  switch (size_18) <default: <L8> [0.00%], case 1: <L4> [0.00%], case 2: <L5> [0.00%], case 4: <L6> [0.00%], case 8: <L7> [0.00%]>

<L4> [0.00%]:
  _19 = MEM[(__u8 *)res_17];
  MEM[(volatile __u8 *)p_16] ={v} _19;
  goto <bb 9>; [0.00%]

<L5> [0.00%]:
  _20 = MEM[(__u16 *)res_17];
  MEM[(volatile __u16 *)p_16] ={v} _20;
  goto <bb 9>; [0.00%]

<L6> [0.00%]:
  _21 = MEM[(__u32 *)res_17];
  MEM[(volatile __u32 *)p_16] ={v} _21;
  goto <bb 9>; [0.00%]

<L7> [0.00%]:
  _22 = MEM[(__u64 *)res_17];
  MEM[(volatile __u64 *)p_16] ={v} _22;
  goto <bb 9>; [0.00%]

<L8> [0.00%]:
  _23 = (long unsigned int) size_18;
  __builtin_memcpy (p_16, res_17, _23);

  <bb 9> [0.00%]:
  _24 = __u.__val;
  ASAN_MARK (POISON, &__u, 8);
  list_14->prev = list_14;
  i_13 = i_4 + 1;

  <bb 10> [0.00%]:
  # i_4 = PHI <i_9(2), i_13(9)>
  if (i_4 <= 9)
    goto <bb 3>; [0.00%]
  else
    goto <bb 11>; [0.00%]

  <bb 11> [0.00%]:
  free (p_8);
  _11 = 0;

<L3> [0.00%]:
  return _11;

}



;; Function _GLOBAL__sub_I_00099_0_main (_GLOBAL__sub_I_00099_0_main, funcdef_no=5, decl_uid=3178, cgraph_uid=3, symbol_order=8)

_GLOBAL__sub_I_00099_0_main ()
{
  <bb 2> [0.00%]:
  __builtin___asan_init ();
  __builtin___asan_version_mismatch_check_v8 ();
  return;

}


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ