Bug 1484290 - There is an illegal address access in dump_entry.c of libncurses.
Summary: There is an illegal address access in dump_entry.c of libncurses.
Keywords:
Status: CLOSED DUPLICATE of bug 1488920
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: ncurses
Version: 7.5-Alt
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: rc
: ---
Assignee: Miroslav Lichvar
QA Contact: qe-baseos-daemons
URL:
Whiteboard:
Depends On:
Blocks: CVE-2017-13733
TreeView+ depends on / blocked
 
Reported: 2017-08-23 08:06 UTC by owl337
Modified: 2018-07-27 15:24 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2018-07-27 15:24:56 UTC


Attachments (Terms of Use)
Triggered by " ./infotocap POC12 " (deleted)
2017-08-23 08:06 UTC, owl337
no flags Details
"./infotocap POC12" (687 bytes, application/x-rar)
2017-08-24 08:53 UTC, owl337
no flags Details

Description owl337 2017-08-23 08:06:03 UTC
Description of problem:

There is an illegal address access in dump_entry.c of libncurses.

Version-Release number of selected component (if applicable):

<= latest version

How reproducible:

./infotocap POC12

Steps to Reproduce:

$ ./../../../infotocap POC12
...
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:rs=\272:\
	:sf=\n:ta=^I:
R裕驭每每:\
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:\
	:ta=^I:
S裕驭[:\
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:\
	:ta=^I:
j裕驭[:\
	:bl=^G:cr=\r:do=\n:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:ta=^I:
Segmentation fault

The GDB debugging information is as follows:
(gdb) set args POC6
(gdb) r

Starting program: /home/icy/secreal/ncurses-6.0-20170819/install/bin/infotocap POC6 
"POC6", line 1, col 9: dubious character `*' in name or alias field
"POC6", line 1, col 10, terminal 'a*9拢驭[': Illegal character (expected alphanumeric or @%&*!#) - '['
"POC6", line 1, col 14, terminal 'a*9拢驭[': unknown capability 'O'
"POC6", line 1, col 21, terminal 'a*9拢驭[': unknown capability '5'
...

Breakpoint 1, fmt_entry (tterm=0x686700, pred=<optimized out>, content_only=<optimized out>, suppress_untranslatable=0, 
    infodump=0, numbers=0) at ../progs/dump_entry.c:996
996			&& !strcmp(reset_2string, termcap_reset))
(gdb) c 
Continuing.
j:\
	:bl=^G:cr=\r:do=\n:kb=^H:kd=\n:kl=^H:nw=\r\n:rs=:sf=\n:ta=^I:
j裕詧拢[M:\
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:rs=\272:\
	:sf=\n:ta=^I:
S裕驭[:\
	:bl=^G:cr=\r:do=\n:kb=^H:kd=\n:kl=^H:nw=\r\n:rs=\272:sf=\n:\
	:ta=^I:
R裕驭每每:\
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:\
	:ta=^I:
j裕詧[M:\
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:rs=\272:\
	:sf=\n:ta=^I:
R裕驭每每:\
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:\
	:ta=^I:
S裕驭[:\
	:bl=^G:cr=\r:do=\n:i2=:i3=:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:\
	:ta=^I:
j裕驭[:\
	:bl=^G:cr=\r:do=\n:kb=^H:kd=\n:kl=^H:nw=\r\n:sf=\n:ta=^I:

Breakpoint 1, fmt_entry (tterm=0x68f600, pred=<optimized out>, content_only=<optimized out>, suppress_untranslatable=0, 
    infodump=0, numbers=0) at ../progs/dump_entry.c:996
996			&& !strcmp(reset_2string, termcap_reset))
(gdb) bt 
#0  fmt_entry (tterm=0x68f600, pred=<optimized out>, content_only=<optimized out>, suppress_untranslatable=0, 
    infodump=0, numbers=0) at ../progs/dump_entry.c:996
#1  0x00000000004195df in dump_entry (tterm=0x68f600, suppress_untranslatable=0, limited=1, numbers=0, pred=0x0)
    at ../progs/dump_entry.c:1513
#2  0x0000000000403e74 in main (argc=<optimized out>, argv=<optimized out>) at ../progs/tic.c:1032
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
__strcmp_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:201
201	../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or directory.

Trigged in:
fmt_entry (tterm=0x68f600, pred=<optimized out>, content_only=<optimized out>, suppress_untranslatable=0, 
    infodump=0, numbers=0) at ../progs/dump_entry.c:996
996			&& !strcmp(reset_2string, termcap_reset))
(gdb) list 
991		    if (init_3string != ABSENT_STRING
992			&& !strcmp(init_3string, termcap_reset))
993			DISCARD(init_3string);
994	
995		    if (reset_2string != ABSENT_STRING
996			&& !strcmp(reset_2string, termcap_reset))
997			DISCARD(reset_2string);
998		}
999	    }
1000	



Actual results:

crash

Expected results:

crash

Additional info:

Credits:

This vulnerability is detected by team OWL337, with our custom fuzzer collAFL. Please contact ganshuitao@gmail.com   and chaoz@tsinghua.edu.cn if you need more info about the team, the tool or the vulnerability.

Comment 2 Thomas E. Dickey 2017-08-24 08:24:14 UTC
The attachment has been deleted; there are no steps to reproduce the issue.

Comment 3 owl337 2017-08-24 08:53:14 UTC
Created attachment 1317519 [details]
"./infotocap POC12"

Comment 4 Thomas E. Dickey 2017-08-25 22:40:00 UTC
The given attachment does not produce the problem.
By the way, the trace uses a different filename.

Comment 5 owl337 2017-08-26 03:13:13 UTC
(In reply to Thomas E. Dickey from comment #4)
> The given attachment does not produce the problem.
> By the way, the trace uses a different filename.

Please set it as follow.
$gdb infotocap
...
(gdb) set args POC12

Comment 6 owl337 2017-08-26 03:20:44 UTC
I check the poc I upstreamed again. It should be correct in the latest version(date:08.19)

Comment 7 Thomas E. Dickey 2017-08-26 13:57:17 UTC
I am still unable to reproduce the problem with this data.

Comment 8 gobaya 2017-11-08 01:11:53 UTC
In curses, there are two kinds of invalid string, ABSENT_STRING (char*)0, and CANCELLED_STRING (char *)(-1). However, in ncurses 6.0, a string will be passed to strcmp if it is not an ABSENT_STRING. strcmp call on a CANCELLED_STRING causes a segment fault.

In ncurses-6.0-20171007, macro VALID_STRING check a string for both ABSENT_STRING and CANCELLED_STRING, only a string that is neither a ABSENT_STRING nor a CANCELLED_STRING will be passed to strcmp.

Comment 9 gobaya 2017-11-08 01:16:05 UTC
Here is the old code that causes the segment fault:
#undef CUR
#define CUR tterm->
    if (outform == 2) {
 if (tterm-> Strings[395] != (char *)0) {
     if (tterm-> Strings[50] != (char *)0
  && !strcmp(tterm-> Strings[50], tterm-> Strings[395]))
  tterm-> Strings[50] = (char *)0;

     if (tterm-> Strings[123] != (char *)0
  && !strcmp(tterm-> Strings[123], tterm-> Strings[395]))
  tterm-> Strings[123] = (char *)0;
 }
    }

Here is the recent code that fails to reproduce the segment fault:#undef CUR
#define CUR tterm->
    if (outform == 2) {
 if (((tterm-> Strings[395]) != (char *)(-1) && (tterm-> Strings[395]) != (char *)0)) {
     if (((tterm-> Strings[50]) != (char *)(-1) && (tterm-> Strings[50]) != (char *)0)
  && !strcmp(tterm-> Strings[50], tterm-> Strings[395]))
  tterm-> Strings[50] = (char *)0;

     if (((tterm-> Strings[123]) != (char *)(-1) && (tterm-> Strings[123]) != (char *)0)
  && !strcmp(tterm-> Strings[123], tterm-> Strings[395]))
  tterm-> Strings[123] = (char *)0;
 }
    }


Note You need to log in before you can comment on or make changes to this bug.