Skip to content

possible UAF in eval_else when fuzzing aug_preview #856

@Anza2001

Description

@Anza2001

Hello, I found a UAF when running the following fuzz driver in OSS-Fuzz environment.

#include "config.h"
#include "augeas.h"
#include "internal.h"
#include "memory.h"
#include "syntax.h"
#include "transform.h"
#include "errcode.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    if (size < 1) {
        return 0; // Not enough data to work with
    }

    // Initialize augeas with default parameters
    struct augeas *aug = aug_init(NULL, NULL, 0);
    if (!aug) {
        return 0; // Failed to initialize augeas
    }

    // Create a null-terminated string from the input data
    char *input_str = (char *)malloc(size + 1);
    if (!input_str) {
        aug_close(aug);
        return 0; // Memory allocation failed
    }
    memcpy(input_str, data, size);
    input_str[size] = '\0';

    // Prepare the output parameter
    char *output_str = NULL;

    // Fuzz the aug_preview function
    int result = aug_preview(aug, input_str, &output_str);

    // Clean up
    free(input_str);
    if (output_str) {
        free(output_str);
    }
    aug_close(aug);

    return 0; // Always return 0
}

Here is the ASAN log:

==12==ERROR: AddressSanitizer: heap-use-after-free on address 0x511000011c68 at pc 0x556cccb9342d bp 0x7ffc389568c0 sp 0x7ffc389568b8
READ of size 8 at 0x511000011c68 thread T0
SCARINESS: 51 (8-byte-read-heap-use-after-free)
    #0 0x556cccb9342c in eval_else /src/augeas/src/pathx.c:1014:16
    #1 0x556cccb89240 in eval_binary /src/augeas/src/pathx.c:1209:9
    #2 0x556cccb89240 in eval_expr /src/augeas/src/pathx.c:1499:9
    #3 0x556cccb7352f in pathx_eval /src/augeas/src/pathx.c:2869:5
    #4 0x556cccb7352f in pathx_first /src/augeas/src/pathx.c:2889:27
    #5 0x556cccb6cd54 in aug_preview /src/augeas/src/augeas.c:1999:12
    #6 0x556cccb58a95 in LLVMFuzzerTestOneInput /src/augeas/augeas_aug_preview_fuzzer.cc:33:18
    #7 0x556ccca0d4d0 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #8 0x556ccca0ccf5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7
    #9 0x556ccca0e4d5 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19
    #10 0x556ccca0f265 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5
    #11 0x556ccc9fe0ab in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6
    #12 0x556ccca29482 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #13 0x7f1f90b0a082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0323ab4806bee6f846d9ad4bccfc29afdca49a58)
    #14 0x556ccc9f092d in _start (/out/augeas_aug_preview_fuzzer+0xb792d)

DEDUP_TOKEN: eval_else--eval_binary--eval_expr
0x511000011c68 is located 104 bytes inside of 256-byte region [0x511000011c00,0x511000011d00)
freed by thread T0 here:
    #0 0x556cccb1968c in realloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:82:3
    #1 0x556cccb98cf4 in mem_realloc_n /src/augeas/src/memory.c:98:11
    #2 0x556cccb92808 in make_value /src/augeas/src/pathx.c:564:13
    #3 0x556cccb92808 in eval_else /src/augeas/src/pathx.c:1013:28
    #4 0x556cccb89240 in eval_binary /src/augeas/src/pathx.c:1209:9
    #5 0x556cccb89240 in eval_expr /src/augeas/src/pathx.c:1499:9
    #6 0x556cccb7352f in pathx_eval /src/augeas/src/pathx.c:2869:5
    #7 0x556cccb7352f in pathx_first /src/augeas/src/pathx.c:2889:27
    #8 0x556cccb6cd54 in aug_preview /src/augeas/src/augeas.c:1999:12
    #9 0x556cccb58a95 in LLVMFuzzerTestOneInput /src/augeas/augeas_aug_preview_fuzzer.cc:33:18
    #10 0x556ccca0d4d0 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #11 0x556ccca0ccf5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7
    #12 0x556ccca0e4d5 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19
    #13 0x556ccca0f265 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5
    #14 0x556ccc9fe0ab in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6
    #15 0x556ccca29482 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #16 0x7f1f90b0a082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0323ab4806bee6f846d9ad4bccfc29afdca49a58)

DEDUP_TOKEN: __interceptor_realloc--mem_realloc_n--make_value
previously allocated by thread T0 here:
    #0 0x556cccb1968c in realloc /src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:82:3
    #1 0x556cccb98cf4 in mem_realloc_n /src/augeas/src/memory.c:98:11
    #2 0x556cccb8150d in make_value /src/augeas/src/pathx.c:564:13
    #3 0x556cccb88442 in eval_filter /src/augeas/src/pathx.c:1457:24
    #4 0x556cccb88442 in eval_expr /src/augeas/src/pathx.c:1496:9
    #5 0x556cccb88137 in eval_binary /src/augeas/src/pathx.c:1169:5
    #6 0x556cccb88137 in eval_expr /src/augeas/src/pathx.c:1499:9
    #7 0x556cccb8803c in eval_binary /src/augeas/src/pathx.c:1164:5
    #8 0x556cccb8803c in eval_expr /src/augeas/src/pathx.c:1499:9
    #9 0x556cccb8803c in eval_binary /src/augeas/src/pathx.c:1164:5
    #10 0x556cccb8803c in eval_expr /src/augeas/src/pathx.c:1499:9
    #11 0x556cccb8803c in eval_binary /src/augeas/src/pathx.c:1164:5
    #12 0x556cccb8803c in eval_expr /src/augeas/src/pathx.c:1499:9
    #13 0x556cccb88137 in eval_binary /src/augeas/src/pathx.c:1169:5
    #14 0x556cccb88137 in eval_expr /src/augeas/src/pathx.c:1499:9
    #15 0x556cccb7352f in pathx_eval /src/augeas/src/pathx.c:2869:5
    #16 0x556cccb7352f in pathx_first /src/augeas/src/pathx.c:2889:27
    #17 0x556cccb6cd54 in aug_preview /src/augeas/src/augeas.c:1999:12
    #18 0x556cccb58a95 in LLVMFuzzerTestOneInput /src/augeas/augeas_aug_preview_fuzzer.cc:33:18
    #19 0x556ccca0d4d0 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:614:13
    #20 0x556ccca0ccf5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:516:7
    #21 0x556ccca0e4d5 in fuzzer::Fuzzer::MutateAndTestOne() /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:760:19
    #22 0x556ccca0f265 in fuzzer::Fuzzer::Loop(std::__Fuzzer::vector<fuzzer::SizedFile, std::__Fuzzer::allocator<fuzzer::SizedFile>>&) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:905:5
    #23 0x556ccc9fe0ab in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:914:6
    #24 0x556ccca29482 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #25 0x7f1f90b0a082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0323ab4806bee6f846d9ad4bccfc29afdca49a58)

DEDUP_TOKEN: __interceptor_realloc--mem_realloc_n--make_value
SUMMARY: AddressSanitizer: heap-use-after-free /src/augeas/src/pathx.c:1014:16 in eval_else
Shadow bytes around the buggy address:
  0x511000011980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x511000011a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x511000011a80: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x511000011b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x511000011b80: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
=>0x511000011c00: fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd
  0x511000011c80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x511000011d00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x511000011d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x511000011e00: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa
  0x511000011e80: 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
==12==ABORTING
MS: 1 CopyPart-; base unit: df1540f40a67178e4c925cbf57d216fad0976944
0xa,0x20,0xa,0x66,0x69,0x6c,0x65,0x73,0x7c,0x4,0x20,0x7c,0x4,0x20,0x65,0x6c,0x73,0x65,0x20,0x86,0xa,0xa,0x7c,0xc2,0xc2,0xc2,0x2e,0x65,0x6c,0x73,0x65,0x20,0x86,0xa,0xa,0x7c,0xc2,0xc2,0xc2,0x2e,0xa,0x7c,0xa,0x86,0xa,0x7c,0x2e,
\012 \012files|\004 |\004 else \206\012\012|\302\302\302.else \206\012\012|\302\302\302.\012|\012\206\012|.
artifact_prefix='augeas_aug_preview_fuzzer_'; Test unit written to augeas_aug_preview_fuzzer_crash-96d565623a8d0be372edad03e38ef4bb824ddb74
Base64: CiAKZmlsZXN8BCB8BCBlbHNlIIYKCnzCwsIuZWxzZSCGCgp8wsLCLgp8CoYKfC4=

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions