Bugzilla will be upgraded to version 5.0. The upgrade date is tentatively scheduled for 2 December 2018, pending final testing and feedback.
Bug 1371630 - Getting KSH Segfault even after applying the errata of #1247383
Getting KSH Segfault even after applying the errata of #1247383
Status: CLOSED ERRATA
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: ksh (Show other bugs)
7.2
Unspecified Unspecified
medium Severity medium
: rc
: ---
Assigned To: Siteshwar Vashisht
Jan Kepler
: Reproducer
Depends On:
Blocks: 1298243 1393867
  Show dependency treegraph
 
Reported: 2016-08-30 12:31 EDT by Filip Krska
Modified: 2017-08-01 12:26 EDT (History)
6 users (show)

See Also:
Fixed In Version: ksh-20120801-34.el7
Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: 1349280
: 1466399 (view as bug list)
Environment:
Last Closed: 2017-08-01 12:26:55 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
ksh-20120801-typeset.patch (716 bytes, patch)
2016-12-14 07:15 EST, Siteshwar Vashisht
no flags Details | Diff


External Trackers
Tracker ID Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2017:1936 normal SHIPPED_LIVE ksh bug fix update 2017-08-01 13:55:48 EDT

  None (edit)
Description Filip Krska 2016-08-30 12:31:33 EDT
ksh-20120801-26.el7.x86_64 reproduces as well

+++ This bug was initially created as a clone of Bug #1349280 +++


--- Additional comment from Filip Krska on 2016-08-30 12:25:19 EDT ---

Minimalistic reproducer:

# cat ksh_typeset.sh
A[0]=$"'"
B[0]=aa
C[0]=aa
typeset -a
# ksh ksh_typeset.sh 
Segmentation fault (core dumped)
Comment 1 Filip Krska 2016-09-16 11:22:47 EDT
When tracing the while loop at typeset.c:1455

 else while(namec--)
        {
                if((np=nv_search(*argv++,root,0)) && np!=onp && (!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)))
                {
                        onp = np;
                        if(name)
                        {
                                char *newname = nv_name(np);
                                if(memcmp(name,newname,len)==0 && newname[len]== '.')
                                        continue;
                                name = 0;
                        }
                        if(flag&NV_ARRAY)
                        {
                                if(nv_aindex(np)>=0)
                                {
                                        if(!(flag&NV_IARRAY))
                                                continue;
                                }
                                else if((flag&NV_IARRAY))
                                        continue;

                        }
                        tp->scanmask = flag&~NV_NOSCOPE;
                        tp->scanroot = root;
                        print_namval(file,np,option,tp);
                        if(!is_abuiltin(np) && nv_isvtree(np))
                        {
                                name = nv_name(np);
                                len = strlen(name);
                        }
                }
        }

it seems that function print_namval(file,np,option,tp); damages argv[]:

(gdb) 
1480				print_namval(file,np,option,tp);
3: argv[1] = 0x7ffff7f905d8 "C"
1: *argv = 0x7ffff7f903b8 "B"
(gdb) n
1481				if(!is_abuiltin(np) && nv_isvtree(np))
3: argv[1] = 0x27275c2724 <Address 0x27275c2724 out of bounds>
1: *argv = 0x7ffff7f903b8 "B"

next cycle of while then leads to segfault because nv_search gets the damaged *argv++ value.
Comment 2 Filip Krska 2016-10-06 11:14:34 EDT
Actually the $ was redundant in the reproducer, following is working as well:

# cat ksh_typeset.sh 
A[0]="'"
B[0]=aa
C[0]=aa
typeset -a


This is what I got when watching *argv, rgv[1]:

(gdb) b typeset.c:1455
Breakpoint 1 at 0x4905aa: file /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c, line 1455.
(gdb) run ksh_typeset.sh
Starting program: /usr/bin/ksh ksh_typeset.sh

Breakpoint 1, print_scan (file=0x79cea0 <_Sfstdout>, flag=4195328, root=0x7ffff7fc8fc0, option=0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:1455
1455		else while(namec--)
(gdb) watch *argv
Watchpoint 2: *argv
(gdb) watch argv[1]
Watchpoint 3: argv[1]
(gdb) c
Continuing.
Watchpoint 2: *argv

Old value = 0x7ffff7f90198 "A"
New value = 0x7ffff7f903b8 "B"
Watchpoint 3: argv[1]

Old value = 0x7ffff7f903b8 "B"
New value = 0x7ffff7f905d8 "C"
0x00000000004905b6 in print_scan (file=0x79cea0 <_Sfstdout>, flag=4195328, root=0x7ffff7fc8fc0, option=0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:1457
1457			if((np=nv_search(*argv++,root,0)) && np!=onp && (!nv_isnull(np) || np->nvfun || nv_isattr(np,~NV_NOFREE)))
(gdb) 
Continuing.
Watchpoint 3: argv[1]

Old value = 0x7ffff7f905d8 "C"
New value = 0x7ffff7f90524 ""
0x00007ffff739b1da in __memmove_sse2 (dest=<optimized out>, src=<optimized out>, len=<optimized out>) at ../string/memmove.c:85
85	      BYTE_COPY_FWD (dstp, srcp, len);
(gdb) bt
#0  0x00007ffff739b1da in __memmove_sse2 (dest=<optimized out>, src=<optimized out>, len=<optimized out>) at ../string/memmove.c:85
#1  0x00000000004fd721 in sfwrite (f=0x79b0e0 <_Stak_data>, buf=0x52ec80, n=2)
    at /usr/src/debug/ksh-20120801/src/lib/libast/sfio/sfwrite.c:138
#2  0x000000000045d21d in sh_fmtq (string=0x7ffff7f90350 "'") at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/string.c:383
#3  0x000000000044f72d in nv_outnode (np=0x7ffff7f90160, out=0x79cea0 <_Sfstdout>, indent=-1, special=0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/nvtree.c:661
#4  0x000000000048d5bd in print_value (iop=0x79cea0 <_Sfstdout>, np=0x7ffff7f90160, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:514
#5  0x0000000000490182 in print_namval (file=0x79cea0 <_Sfstdout>, np=0x7ffff7f90160, flag=0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:1367
#6  0x00000000004906f3 in print_scan (file=0x79cea0 <_Sfstdout>, flag=4195328, root=0x7ffff7fc8fc0, option=0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:1480
#7  0x000000000048e8be in setall (argv=0x7ffff7fac698, flag=4195840, troot=0x7ffff7fc8fc0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:860
#8  0x000000000048d226 in b_typeset (argc=2, argv=0x7ffff7fac698, context=0x79f830 <sh+1296>)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:459
#9  0x000000000046a290 in sh_exec (t=0x7ffff7fac7d1, flags=4) at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/xec.c:1410
#10 0x00000000004074ec in exfile (shp=0x7ffff7fac7d1, iop=0x52ec80, fno=36) at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/main.c:581
#11 0x000000000040690c in sh_main (ac=2, av=0x7fffffffe338, userinit=0x0) at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/main.c:353
#12 0x0000000000405ca2 in main (argc=2, argv=0x7fffffffe338) at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/pmain.c:45
(gdb) c
Continuing.
Watchpoint 3: argv[1]

Old value = 0x7ffff7f90524 ""
New value = 0x7ffff7f92724 ""
0x00007ffff739b1da in __memmove_sse2 (dest=<optimized out>, src=<optimized out>, len=<optimized out>) at ../string/memmove.c:85
85	      BYTE_COPY_FWD (dstp, srcp, len);
(gdb) c
Continuing.
Watchpoint 3: argv[1]

Old value = 0x7ffff7f92724 ""
New value = 0x7ffff75c2724 <Address 0x7ffff75c2724 out of bounds>
sh_fmtq (string=0x7ffff7f90350 "'") at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/string.c:445
445					stakputc(c);
(gdb) bt
#0  sh_fmtq (string=0x7ffff7f90350 "'") at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/string.c:445
#1  0x000000000044f72d in nv_outnode (np=0x7ffff7f90160, out=0x79cea0 <_Sfstdout>, indent=-1, special=0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/nvtree.c:661
#2  0x000000000048d5bd in print_value (iop=0x79cea0 <_Sfstdout>, np=0x7ffff7f90160, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:514
#3  0x0000000000490182 in print_namval (file=0x79cea0 <_Sfstdout>, np=0x7ffff7f90160, flag=0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:1367
#4  0x00000000004906f3 in print_scan (file=0x79cea0 <_Sfstdout>, flag=4195328, root=0x7ffff7fc8fc0, option=0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:1480
#5  0x000000000048e8be in setall (argv=0x7ffff7fac698, flag=4195840, troot=0x7ffff7fc8fc0, tp=0x7fffffffd9a0)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:860
#6  0x000000000048d226 in b_typeset (argc=2, argv=0x7ffff7fac698, context=0x79f830 <sh+1296>)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/bltins/typeset.c:459
#7  0x000000000046a290 in sh_exec (t=0x799ec4 <_ast_info+36>, flags=4) at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/xec.c:1410
#8  0x00000000004074ec in exfile (shp=0x799ec4 <_ast_info+36>, iop=0x7ffff7f90350, fno=-134559789)
    at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/main.c:581
#9  0x000000000040690c in sh_main (ac=2, av=0x7fffffffe338, userinit=0x0) at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/main.c:353
#10 0x0000000000405ca2 in main (argc=2, argv=0x7fffffffe338) at /usr/src/debug/ksh-20120801/src/cmd/ksh93/sh/pmain.c:45


I don't know yet which function is to blame but imho argv[] shall not be altered inside print_namval()...
Comment 3 Siteshwar Vashisht 2016-12-12 18:14:50 EST
Thanks Filip for the reproducer and debugging information.

I will add some more notes.

It seems ksh handles "'" specially and it goes through below codepath in sh_fmtq() function in src/cmd/ksh93/sh/string.c :

char    *sh_fmtq(const char *string)
...
...

#if SHOPT_MULTIBYTE
                if(c=='\'' || c>=128 || c<0 || !iswprint(c)) 
#else
                if(c=='\'' || !isprint(c))
#endif /* SHOPT_MULTIBYTE */
                        state = 2;

...
...
        }
        if(state<2)
        {
            ...
            ...
        }
        else
        {
                int isbyte=0;
                stakwrite("$'",2);

...
...
                        if(state)
                        {
                                stakputc('\\');
                                stakputc(c);
                        }
...
...
                stakputc('\'');
        }
        stakputc(0);
....


So at the end "'" is being expanded to "$'\\''".

This codepath is probably corrupting the stack data structure that ksh maintains.
Comment 4 Siteshwar Vashisht 2016-12-14 07:15 EST
Created attachment 1231648 [details]
ksh-20120801-typeset.patch

Fix a bug in memory allocation while listing indexed arrays with typeset
Comment 12 errata-xmlrpc 2017-08-01 12:26:55 EDT
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, 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-2017:1936

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