Markakd / safe_tcmalloc

Apache License 2.0
0 stars 0 forks source link

bug in 500.perlbench_r(need to be reported) #3

Open kitaharazy opened 2 years ago

kitaharazy commented 2 years ago

Trigger the bug

In short, in realloc, we gonna call void Free(void *ptr, void *end) in

/home/roland/github/violet/src/safe_tcmalloc/tcmalloc/span.h:165,

during the while loop, PL_tmps_stack[330]->sv_any is end-0x10,

and it will be poisioned by Free, cur->addr == &PL_tmps_stack[330]->sv_any.

After being poisioned, PL_tmps_stack[330]->sv_any will be accessed in the following codes, so there is a segfault.


In case 500, there are several global vars, such as (SV **)PL_tmps_stack , PL_tmps_ix , PL_tmps_max, these three vars are related to this bug.

About PL_tmps_stack[330], PL_tmps_stack[330]->sv_any will be poisioned during realloc PL_tmps_stack[]

the backtrace:

#0  tcmalloc::tcmalloc_internal::EscapeTable::Free (this=0x56c33f760f78, ptr=0x56c33fbb2c80, end=0x56c33fbb3900) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/span.h:188

#1  0x00007ffff74bdef9 in tcmalloc::tcmalloc_internal::(anonymous namespace)::do_free_with_size_class<false, (tcmalloc::tcmalloc_internal::Hooks)0> (size_class=0, ptr=0x56c33fbb2c80) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/span.h:428

#2  tcmalloc::tcmalloc_internal::(anonymous namespace)::do_free (ptr=0x56c33fbb2c80) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/tcmalloc.cc:1095

#3  do_realloc (new_size=<optimized out>, old_ptr=0x56c33fbb2c80) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/tcmalloc.cc:1872

#4  TCMallocInternalRealloc (old_ptr=0x56c33fbb2c80, new_size=<optimized out>) at /home/roland/github/violet/src/safe_tcmalloc/tcmalloc/tcmalloc.cc:1888

#5  0x00000000004f5180 in Perl_safesysrealloc (where=0x56c33f760f78, size=<optimized out>) at util.c:278

#6  0x00000000004bc8ba in Perl_tmps_grow_p (ix=ix@entry=386) at scope.c:161

in backtrace, &PL_tmps_stack[0] = 0x56c33fbb2c80 , &PL_tmps_stack[330] = 0x56c33fbb36d0 , &PL_tmps_stack[330]->sv_any = 0x56c33eba82e8 , PL_tmps_stack[330]->sv_any = 0x56c33fbb38f0(before being poisioned)

In do_free_with_size_class<false, (tcmalloc::tcmalloc_internal::Hooks)0> (size_class=0, ptr=PL_tmps_stack) span_->GetEscapeTable()->Free(ptr); will finally be called as:

span_->GetEscapeTable()->Free(ptr, (char*)ptr + obj_size);

Therefore, as for PL_tmps_stack[330]->sv_any = 0x56c33fbb38f0, it is in the range of (ptr , end = obj_size+ptr) , and will be poisioned in the loop at tcmalloc/span.h:165


    // ptr=0x56c33fbb2c80, end=0x56c33fbb3900 

    while (cur) {
      if (ptr <= cur->addr && cur->addr < end) {
        struct escape* e = cur;

        if (pre == nullptr) {
          head = e->next;
          cur  = e->next;
        } else {
          pre->next = e->next;
          cur = e->next;
        }

        while (e->escape_list) {
          struct escape *cur = e->escape_list;
          e->escape_list = cur->next;

          void* cur_addr = *(reinterpret_cast<void**>(cur->addr));
          if (ptr <= cur_addr && cur_addr < end) {
            *(reinterpret_cast<size_t*>(cur->addr)) |= (size_t) 0xdeadbeef00000000;
          }
          delete_escape(cur);
        }
        delete_escape(e);
      } else {
        pre = cur;
        cur = cur->next;
      }
    }

debug script

#save as a.gdb
#`source a.gdb` after run your gdb
b *(Perl_tmps_grow_p+85) if (unsigned long)$rsi >  0x1000

b *(Perl_free_tmps+46) if (*(unsigned long *)PL_tmps_stack[PL_tmps_ix+1]) > 0x66c33e9088b0 && (unsigned long)(PL_tmps_ix) == 329

run -I./lib checkspam.pl 2500 5 25 11 150 1 1 1 1 > checkspam.2500.5.25.11.150.1.1.1.1.out 2>> checkspam.2500.5.25.11.150.1.1.1.1.err

First you will stop at Renew() before realloc is called, then use watch PL_tmps_stack[330]->sv_any and continue, you will stop at delete_escape(cur); in safe_tcmalloc/tcmalloc/span.h:188

Markakd commented 2 years ago

I feel like this is a bug. because the memory indeed is freed by realloc.

Markakd commented 2 years ago

We should report this bug to the developers. This benchmark has been run by many tools, none of them found this bug.

kitaharazy commented 2 years ago

We should report this bug to the developers. This benchmark has been run by many tools, none of them found this bug.

Sure, I found the webpage: https://www.spec.org/spec/contact.html

As what they say:

Please direct general technical questions regarding SPEC benchmark products to SPEC's staff at support@spec.org. We can provide assistance only with issues directly related to running the benchmark software. Examples of support that SPEC cannot provide include: hardware installation issues; hardware problems; non-SPEC software installation issues; non-SPEC software problems; hardware or software specific tuning.

Should we directly drop a mail to support@spec.org, or we need to find the developers of SPECCPU?