Uploaded image for project: 'Qpid Dispatch'
  1. Qpid Dispatch
  2. DISPATCH-2060

use-after free in qd_alloc_deref_safe_ptr if a pool item has been freed due to global_free_list size limit

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Trivial
    • Resolution: Feedback Received
    • 1.15.0, 1.16.0
    • None
    • None
    • None

    Description

      This is something that is unlikely to occur because the global_free_list size limit is unset by default and as far as I can tell, nobody sets it (except of one small unittest). But if it is set, then it may happen that an item gets freed while there is still a safe pointer pointing to it. The check in qd_alloc_deref_safe_ptr to see if safe pointer is still valid involves accessing the item memory. Since that's been freed, the operation is a use-after-free.

      static char *test_safe_references(void *context)
      {
          object_t    *obj = new_object_t();
          object_t_sp  safe_obj;
      
          set_safe_ptr_object_t(obj, &safe_obj);
          object_t *alias = safe_deref_object_t(safe_obj);
      
          if (obj != alias)
              return "Safe alias was not equal to the original pointer";
      
          free_object_t(obj);
          alias = safe_deref_object_t(safe_obj);  // HERE is ../tests/alloc_test.c:90
      
          if (alias != 0)
              return "Safe dereference of a freed object was not null";
      
          return 0;
      }
      
      ==21009==ERROR: AddressSanitizer: heap-use-after-free on address 0x611000003f48 at pc 0x7fcf829bb060 bp 0x7ffc752e1780 sp 0x7ffc752e1778
      READ of size 4 at 0x611000003f48 thread T0
          #0 0x7fcf829bb05f in qd_alloc_sequence ../src/alloc_pool.c:523
          #1 0x4161f2 in qd_alloc_deref_safe_ptr ../include/qpid/dispatch/alloc_pool.h:102
          #2 0x4161f2 in safe_deref_object_t ../tests/alloc_test.c:35
          #3 0x41638c in test_safe_references ../tests/alloc_test.c:90
          #4 0x4163dc in alloc_tests ../tests/alloc_test.c:105
          #5 0x406c30 in main ../tests/run_unit_tests.c:65
          #6 0x7fcf81545cbc in __libc_start_main (/nix/store/q53f5birhik4dxg3q3r2g5f324n7r5mc-glibc-2.31-74/lib/libc.so.6+0x23cbc)
          #7 0x404959 in _start (/home/jdanek/repos/qpid/qpid-dispatch/cmake-build-debug-asan/tests/unit_tests+0x404959)
      
      0x611000003f48 is located 136 bytes inside of 192-byte region [0x611000003ec0,0x611000003f80)
      freed by thread T0 here:
          #0 0x7fcf8318eb6f in __interceptor_free (/nix/store/g40sl3zh3nv52vj0mrl4iki5iphh5ika-gcc-10.2.0-lib/lib/libasan.so.6+0xacb6f)
          #1 0x7fcf829badae in qd_dealloc ../src/alloc_pool.c:503
          #2 0x41609d in free_object_t ../tests/alloc_test.c:35
          #3 0x41636a in test_safe_references ../tests/alloc_test.c:89
          #4 0x4163dc in alloc_tests ../tests/alloc_test.c:105
          #5 0x406c30 in main ../tests/run_unit_tests.c:65
          #6 0x7fcf81545cbc in __libc_start_main (/nix/store/q53f5birhik4dxg3q3r2g5f324n7r5mc-glibc-2.31-74/lib/libc.so.6+0x23cbc)
      
      previously allocated by thread T0 here:
          #0 0x7fcf8318fa3c in __interceptor_posix_memalign (/nix/store/g40sl3zh3nv52vj0mrl4iki5iphh5ika-gcc-10.2.0-lib/lib/libasan.so.6+0xada3c)
          #1 0x7fcf829b78ea in qd_alloc ../src/alloc_pool.c:398
          #2 0x41607a in new_object_t ../tests/alloc_test.c:35
          #3 0x4162e8 in test_safe_references ../tests/alloc_test.c:80
          #4 0x4163dc in alloc_tests ../tests/alloc_test.c:105
          #5 0x406c30 in main ../tests/run_unit_tests.c:65
          #6 0x7fcf81545cbc in __libc_start_main (/nix/store/q53f5birhik4dxg3q3r2g5f324n7r5mc-glibc-2.31-74/lib/libc.so.6+0x23cbc)
      
      SUMMARY: AddressSanitizer: heap-use-after-free ../src/alloc_pool.c:523 in qd_alloc_sequence
      Shadow bytes around the buggy address:
        0x0c227fff8790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
        0x0c227fff87a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
        0x0c227fff87b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
        0x0c227fff87c0: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
        0x0c227fff87d0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
      =>0x0c227fff87e0: fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd fd
        0x0c227fff87f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
        0x0c227fff8800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
        0x0c227fff8810: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
        0x0c227fff8820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
        0x0c227fff8830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      Shadow byte legend (one shadow byte represents 8 application bytes):
        Addressable:           00
        Partially addressable: 01 02 03 04 05 06 07 
        Heap left redzone:       fa
        Freed heap region:       fd
        Stack left redzone:      f1
        Stack mid redzone:       f2
        Stack right redzone:     f3
        Stack after return:      f5
        Stack use after scope:   f8
        Global redzone:          f9
        Global init order:       f6
        Poisoned by user:        f7
        Container overflow:      fc
        Array cookie:            ac
        Intra object redzone:    bb
        ASan internal:           fe
        Left alloca redzone:     ca
        Right alloca redzone:    cb
        Shadow gap:              cc
      ==21009==ABORTING
      

      Attachments

        Issue Links

          Activity

            People

              jdanek Jiri Daněk
              jdanek Jiri Daněk
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: