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
Target Upstream Version:


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   and chaoz.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.