Bug 1784579

Summary: RHEL-7: col struct char_str c_column field should be of unsigned type and/or larger than 16 bit
Product: Red Hat Enterprise Linux 7 Reporter: Paulo Andrade <pandrade>
Component: util-linuxAssignee: Karel Zak <kzak>
Status: CLOSED ERRATA QA Contact: Radka Brychtova <rskvaril>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 7.7CC: casantos, kwalker
Target Milestone: rcFlags: casantos: needinfo-
casantos: needinfo-
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: util-linux-2.23.2-64.el7 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
: 1803753 (view as bug list) Environment:
Last Closed: 2020-09-29 20:09:52 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:
Bug Depends On:    
Bug Blocks: 1803753    

Description Paulo Andrade 2019-12-17 18:40:42 UTC
The data type is:

typedef struct char_str {
#define	CS_NORMAL	1
#define	CS_ALTERNATE	2
	short		c_column;	/* column character is in */
	CSET		c_set;		/* character set (currently only 2) */
	wchar_t		c_char;		/* character in question */
	int		c_width;	/* character width */
} CHAR;

and the c_column field is set from the variable:

	int cur_col;			/* current column */

  Apparently the reproducer file was lost, but upon the proper
input, it will execute in flush_line():

		for (i = nchars, c = l->l_line; --i >= 0; c++)
			count[c->c_column]++;

and c->c_column might be negative, as is in a sample coredump:

(gdb) p *c
$1 = {c_column = -32760, c_set = 1 '\001', c_char = 56 L'8', c_width = 1}

if it were unsigned, the crash would not happen, as it would
be guaranteed to be positive and less than l->l_max_col.

(gdb) p *l
$2 = {l_line = 0x7fde4a203010, l_prev = 0x1397878, l_next = 0x0, l_lsize = 11520, l_line_len = 10033, l_needs_sort = 1, l_max_col = 65984}

l->l_max_col is of type int, so, for safety it could be a good
idea to also make it unsigned, besides unlikely to have col input
with 2G columns on a line.

Comment 2 Carlos Santos 2019-12-17 19:35:04 UTC
Already fixed upstream:

commit 004356f05018e3bfcaddd2652846659a4d8481f3
Author: Karel Zak <kzak>
Date:   Tue Feb 5 12:06:00 2019 +0100

    col: make flush_line() a little bit robust
    
    The code is horrible. The core of the problem are signed integers
    and no check for the limits.
    
    This patch fixes c->c_column = cur_col; where c_column is "short"
    and "cur_col" is int. Let's use "int" for all the variables. It's
    really not perfect as for bigger lines it can segfault again...
    
    The patch also removes some unnecessary static variables.
    
    Addresses: https://github.com/karelzak/util-linux/issues/749
    Signed-off-by: Karel Zak <kzak>

Comment 5 Karel Zak 2020-02-17 11:05:34 UTC
I do not see problem to backport the patch to RHEL-7.9 and RHEL-8.3  (it's probably too late for 8.2).

I'll clone it for RHEL-8.

Comment 12 errata-xmlrpc 2020-09-29 20:09:52 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (util-linux bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2020:3963