Bug 1919212

Summary: Out of bounds read in function ml_flush_line() when input craft vimscript file
Product: [Fedora] Fedora Reporter: 1vanChen <houyunsong>
Component: vimAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED NOTABUG QA Contact:
Severity: high Docs Contact:
Priority: unspecified    
Version: rawhideCC: gchamoul, mcascell, zdohnal
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: vim-8.2.2529-1.fc33 vim-8.2.2541-1.fc33 vim-8.2.2541-1.fc32 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2021-02-20 01:25:57 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
poc
none
reduced poc file none

Description 1vanChen 2021-01-22 12:09:37 UTC
Created attachment 1749721 [details]
poc

To Reproduce

```shell
vim -u NONE -X -Z -e -s -S poc -c :qa!
```

Debug Info

```shell
/src/vim# gdb --args src/vim -u NONE -X -Z -e -s -S /mnt/disk/out/vim/vim-fuzzer-out/SFeBCp/crashes/id:000066,sig:11,src:051754,op:miller,rep:4 -c :qa!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
RAX: 0x1
RBX: 0x8f3680 --> 0x20 (' ')
RCX: 0x24b82e7b00000000
RDX: 0x92e0b9ec
RSI: 0x9053c0 --> 0x0
RDI: 0x3f ('?')
RBP: 0x9025a0 --> 0xc4400006461 ('ad')
RSP: 0x7fffffff9fe0 --> 0x6e0000005b ('[')
RIP: 0x4c6c5c (<ml_flush_line+124>:     mov    r8d,DWORD PTR [rbp+rdx*1+0x18])
R8 : 0x2
R9 : 0x9072e0 --> 0xc23f776439760a09
R10: 0x8f3680 --> 0x20 (' ')
R11: 0x0
R12: 0x0
R13: 0xff65625a24b82e7b
R14: 0xff65625a24b82e7c
R15: 0x9072e0 --> 0xc23f776439760a09
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x4c6c51 <ml_flush_line+113>:        shl    rcx,0x20
   0x4c6c55 <ml_flush_line+117>:        mov    rdx,rcx
   0x4c6c58 <ml_flush_line+120>:        sar    rdx,0x1e
=> 0x4c6c5c <ml_flush_line+124>:        mov    r8d,DWORD PTR [rbp+rdx*1+0x18]
   0x4c6c61 <ml_flush_line+129>:        mov    edx,r8d
   0x4c6c64 <ml_flush_line+132>:        and    edx,0x7fffffff
   0x4c6c6a <ml_flush_line+138>:        test   r13d,r13d
   0x4c6c6d <ml_flush_line+141>:        je     0x4c6c9f <ml_flush_line+191>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffff9fe0 --> 0x6e0000005b ('[')
0008| 0x7fffffff9fe8 --> 0x0
0016| 0x7fffffff9ff0 --> 0x0
0024| 0x7fffffff9ff8 --> 0x7c00000077 ('w')
0032| 0x7fffffffa000 --> 0x6e0000005b ('[')
0040| 0x7fffffffa008 --> 0x0
0048| 0x7fffffffa010 --> 0x0
0056| 0x7fffffffa018 --> 0x8f3680 --> 0x20 (' ')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000000004c6c5c in ml_flush_line (buf=buf@entry=0x8f3680) at memline.c:3918
3918                start = ((dp->db_index[idx]) & DB_INDEX_MASK);
gdb-peda$ bt
#0  0x00000000004c6c5c in ml_flush_line (buf=buf@entry=0x8f3680) at memline.c:3918
#1  0x00000000004ca623 in ml_get_buf (buf=buf@entry=0x8f3680, lnum=0x1, lnum@entry=0xff65625a24b82e7c, will_change=will_change@entry=0x1) at memline.c:2591
#2  0x00000000005be656 in get_text_props (buf=0x8f3680, lnum=0xff65625a24b82e7c, props=<optimized out>, will_change=0x1) at textprop.c:370
#3  adjust_prop_columns (lnum=0xff65625a24b82e7c, col=col@entry=0x0, bytes_added=0x1, flags=flags@entry=0x0) at textprop.c:1332
#4  0x00000000004aa172 in set_indent (size=<optimized out>, flags=flags@entry=0x4) at indent.c:787
#5  0x00000000004aa842 in op_reindent (oap=oap@entry=0x7fffffffa358, how=0x418c80 <get_c_indent>) at indent.c:1020
#6  0x00000000004f3116 in do_pending_operator (cap=cap@entry=0x7fffffffa2c0, old_col=old_col@entry=0x0, gui_yank=<optimized out>, gui_yank@entry=0x0) at ops.c:3957
#7  0x00000000004e35dc in normal_cmd (oap=oap@entry=0x7fffffffa358, toplevel=toplevel@entry=0x1) at normal.c:1123
#8  0x0000000000629209 in main_loop (cmdwin=cmdwin@entry=0x0, noexmode=noexmode@entry=0x1) at main.c:1473
#9  0x000000000046dc11 in do_exedit (eap=0x7fffffffa4a0, old_curwin=<optimized out>) at ex_docmd.c:6646
#10 0x000000000046897a in do_one_cmd (cmdlinep=0x7fffffffa478, flags=0x2, cstack=0x7fffffffa658, fgetline=0x0, cookie=0x0) at ex_docmd.c:2588
#11 do_cmdline (cmdline=<optimized out>, fgetline=<optimized out>, fgetline@entry=0x0, cookie=<optimized out>, cookie@entry=0x0, flags=flags@entry=0x2) at ex_docmd.c:1003
#12 0x0000000000464303 in global_exe_one (cmd=0x904f84 "vi|", '8' <repeats 25 times>, "=88888888%888g$88MgkggggJgg5f\337nM\204\210!mmm", lnum=<optimized out>) at ex_cmds.c:4787
#13 global_exe (cmd=cmd@entry=0x904f84 "vi|", '8' <repeats 25 times>, "=88888888%888g$88MgkggggJgg5f\337nM\204\210!mmm") at ex_cmds.c:4963
#14 0x0000000000464233 in ex_global (eap=0x7fffffffafb0) at ex_cmds.c:4924
#15 0x000000000046897a in do_one_cmd (cmdlinep=0x7fffffffaf88, flags=0x7, cstack=0x7fffffffb168, fgetline=0x566f30 <getsourceline>, cookie=0x7fffffffb900) at ex_docmd.c:2588
#16 do_cmdline (cmdline=<optimized out>, cmdline@entry=0x904e50 "", fgetline=<optimized out>, cookie=<optimized out>, cookie@entry=0x7fffffffb900, flags=flags@entry=0x7) at ex_docmd.c:1003
#17 0x0000000000566d15 in do_source (fname=<optimized out>, fname@entry=0x8f8ef3 "/mnt/disk/out/vim/vim-fuzzer-out/SFeBCp/crashes/id:000066,sig:11,src:051754,op:miller,rep:4", check_other=<optimized out>,
    check_other@entry=0x0, is_vimrc=is_vimrc@entry=0x0, ret_sid=<optimized out>, ret_sid@entry=0x0) at scriptfile.c:1401
#18 0x0000000000566489 in cmd_source (fname=0x8f8ef3 "/mnt/disk/out/vim/vim-fuzzer-out/SFeBCp/crashes/id:000066,sig:11,src:051754,op:miller,rep:4", eap=<optimized out>) at scriptfile.c:971
#19 0x000000000046897a in do_one_cmd (cmdlinep=0x7fffffffb9f8, flags=0xb, cstack=0x7fffffffbbd8, fgetline=0x0, cookie=0x0) at ex_docmd.c:2588
#20 do_cmdline (cmdline=<optimized out>, fgetline=<optimized out>, fgetline@entry=0x0, cookie=<optimized out>, cookie@entry=0x0, flags=flags@entry=0xb) at ex_docmd.c:1003
#21 0x00000000004692de in do_cmdline_cmd (cmd=0x3f <error: Cannot access memory at address 0x3f>) at ex_docmd.c:592
#22 0x000000000062860d in exe_commands (parmp=<optimized out>) at main.c:3056
#23 vim_main2 () at main.c:760
#24 0x0000000000627772 in main (argc=<optimized out>, argc@entry=0xb, argv=<optimized out>, argv@entry=0x7fffffffe518) at main.c:412
#25 0x00007ffff72f7840 in __libc_start_main (main=0x625f40 <main>, argc=0xb, argv=0x7fffffffe518, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe508)
    at ../csu/libc-start.c:291
#26 0x0000000000404269 in _start ()
```



lnum variable size is not checked, causing dp->db_index[idx] to have out-of-bounds reads, which may cause out-of-bounds writes in the subsequent process

```c
 //src/memline.c L3908
    lnum = buf->b_ml.ml_line_lnum;
	new_line = buf->b_ml.ml_line_ptr;

	hp = ml_find_line(buf, lnum, ML_FIND);
	if (hp == NULL)
	    siemsg(_("E320: Cannot find line %ld"), lnum);
	else
	{
	    dp = (DATA_BL *)(hp->bh_data);
	    idx = lnum - buf->b_ml.ml_locked_low;
	    start = ((dp->db_index[idx]) & DB_INDEX_MASK);
                  ^^^^^^^^^^^^^^^^^^
	    old_line = (char_u *)dp + start;
	    if (idx == 0)	// line is last in block
		old_len = dp->db_txt_end - start;
	    else		// text of previous line follows
		old_len = (dp->db_index[idx - 1] & DB_INDEX_MASK) - start;
	    new_len = buf->b_ml.ml_line_len;
	    extra = new_len - old_len;	    // negative if lines gets smaller
```





Environment:

- version : commit e2edc2ed4a9a229870b1e1811b0ecf045b84e429
- OS: Ubuntu 16.04



Additional context

compile argument:

```shell
#!/bin/bash -eux
export CC="clang-11"
export CXX="clang-11++"
cd /src/vim/ && ./configure --with-features=huge --enable-gui=none && make
```



Credit: 1vanChen of NSFOCUS Security Team

Comment 1 Zdenek Dohnal 2021-01-25 05:37:54 UTC
Hi,

thank you for reporting the issue!

I'll pass the issue to security team and report it upstream.

Comment 3 1vanChen 2021-01-26 06:13:03 UTC
Created attachment 1750764 [details]
reduced poc file

Simplified sample is provided

Comment 4 Mauro Matteo Cascella 2021-02-09 15:24:35 UTC
Hello,

It is unclear to me how this could be exploited to attack a user. It seems like the user would need to source a local vimscript to make VIM crash, thus effectively attacking themselves. I think we can consider vimscript to be trusted input, as a result I don't see any trust boundary crossed. Of course, this is clearly a bug that should be fixed whether or not it is considered security relevant.

Comment 5 Fedora Update System 2021-02-18 09:34:04 UTC
FEDORA-2021-164265f25a has been submitted as an update to Fedora 33. https://bodhi.fedoraproject.org/updates/FEDORA-2021-164265f25a

Comment 6 Fedora Update System 2021-02-18 09:34:50 UTC
FEDORA-2021-01b3981cc5 has been submitted as an update to Fedora 32. https://bodhi.fedoraproject.org/updates/FEDORA-2021-01b3981cc5

Comment 7 Fedora Update System 2021-02-19 01:59:47 UTC
FEDORA-2021-01b3981cc5 has been pushed to the Fedora 32 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2021-01b3981cc5`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2021-01b3981cc5

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 8 Fedora Update System 2021-02-19 02:03:43 UTC
FEDORA-2021-164265f25a has been pushed to the Fedora 33 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2021-164265f25a`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2021-164265f25a

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 9 Fedora Update System 2021-02-20 01:25:57 UTC
FEDORA-2021-164265f25a has been pushed to the Fedora 33 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 10 Fedora Update System 2021-02-22 07:43:31 UTC
FEDORA-2021-5be90ab004 has been submitted as an update to Fedora 33. https://bodhi.fedoraproject.org/updates/FEDORA-2021-5be90ab004

Comment 11 Fedora Update System 2021-02-22 08:02:41 UTC
FEDORA-2021-fb090f432a has been submitted as an update to Fedora 32. https://bodhi.fedoraproject.org/updates/FEDORA-2021-fb090f432a

Comment 12 Fedora Update System 2021-02-24 21:39:41 UTC
FEDORA-2021-fb090f432a has been pushed to the Fedora 32 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2021-fb090f432a`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2021-fb090f432a

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 13 Fedora Update System 2021-02-24 21:55:01 UTC
FEDORA-2021-5be90ab004 has been pushed to the Fedora 33 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2021-5be90ab004`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2021-5be90ab004

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 14 Fedora Update System 2021-02-26 01:08:58 UTC
FEDORA-2021-5be90ab004 has been pushed to the Fedora 33 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 15 Fedora Update System 2021-03-08 20:13:43 UTC
FEDORA-2021-fb090f432a has been pushed to the Fedora 32 stable repository.
If problem still persists, please make note of it in this bug report.