[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: core dump analysis, was Re: stack smashing detected



On Mon, 3 Apr 2023, Michael Schmitz wrote:

> On 2/04/23 22:46, Finn Thain wrote:
> 
> > This is odd:
> >
> > https://sources.debian.org/src/dash/0.5.12-2/src/jobs.c/?hl=1165#L1165
> >
> >    1176          do {
> >    1177                  gotsigchld = 0;
> >    1178                  do
> >    1179                          err = wait3(status, flags, NULL);
> >    1180                  while (err < 0 && errno == EINTR);
> >    1181
> >    1182                  if (err || (err = -!block))
> >    1183                          break;
> >    1184
> >    1185                  sigblockall(&oldmask);
> >    1186
> >    1187                  while (!gotsigchld && !pending_sig)
> >    1188                          sigsuspend(&oldmask);
> >    1189
> >    1190                  sigclearmask();
> >    1191          } while (gotsigchld);
> >    1192
> >    1193  return err;
> >
> > Execution of dash under gdb doesn't seem to agree with the source code
> > above.
> >
> > If wait3() returns the child pid then the break should execute. And it
> > does return the pid (4107) but the while loop was not terminated. Hence
> > wait3() was called again and the same breakpoint was hit again. Also, the
> 
> I wonder whether line 1182 got miscompiled by gcc. As err == 4107 it's > 
> 0 and the break clearly ought to have been taken, and the second 
> condition (which changes err) does not need to be examined.  Do the same 
> ordering constraints apply to '||' as to '&&' ?
> 

AFAICT, the source code is valid. This article has some information: 
https://stackoverflow.com/questions/628526/is-short-circuiting-logical-operators-mandated-and-evaluation-order

It looks like I messed up. waitproc() appears to have been invoked
twice, which is why wait3 was invoked twice...

GNU gdb (Debian 13.1-2) 13.1
...
(gdb) set osabi GNU/Linux
(gdb) file /bin/dash
Reading symbols from /bin/dash...
Reading symbols from /usr/lib/debug/.build-id/aa/4160f84f3eeee809c554cb9f3e1ef0686b8dcc.debug...
(gdb) b waitproc
Breakpoint 1 at 0xc346: file jobs.c, line 1168.
(gdb) b jobs.c:1180
Breakpoint 2 at 0xc390: file jobs.c, line 1180.
(gdb) run
Starting program: /usr/bin/dash 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/m68k-linux-gnu/libthread_db.so.1".
# x=$(:)
[Detaching after fork from child process 570]

Breakpoint 1, waitproc (status=0xeffff86a, block=1) at jobs.c:1168
1168    jobs.c: No such file or directory.
(gdb) c
Continuing.

Breakpoint 2, waitproc (status=0xeffff86a, block=1) at jobs.c:1180
1180    in jobs.c
(gdb) info locals
oldmask = {__val = {1997799424, 49154, 396623872, 184321, 3223896090, 53249, 
    3836788738, 1049411610, 867225601, 3094609920, 0, 1048580, 2857693183, 
    4184129547, 3435708442, 863764480, 184321, 3844141055, 4190425089, 
    4127248385, 3094659084, 597610497, 4135112705, 3844079616, 131072, 
    37355520, 184320, 3878473729, 3844132865, 3094663168, 3549089793, 
    3844132865}}
flags = 2
err = 570
oldmask = <optimized out>
flags = <optimized out>
err = <optimized out>
(gdb) c
Continuing.

Breakpoint 1, waitproc (status=0xeffff86a, block=0) at jobs.c:1168
1168    in jobs.c
(gdb) c
Continuing.

Breakpoint 2, waitproc (status=0xeffff86a, block=0) at jobs.c:1180
1180    in jobs.c
(gdb) info locals
oldmask = {__val = {1997799424, 49154, 396623872, 184321, 3223896090, 53249, 
    3836788738, 1049411610, 867225601, 3094609920, 0, 1048580, 2857693183, 
    4184129547, 3435708442, 863764480, 184321, 3844141055, 4190425089, 
    4127248385, 3094659084, 597610497, 4135112705, 3844079616, 131072, 
    37355520, 184320, 3878473729, 3844132865, 3094663168, 3549089793, 
    3844132865}}
flags = 3
err = -1
oldmask = <optimized out>
flags = <optimized out>
err = <optimized out>
(gdb) c
Continuing.
# 

> What does the disassembly of this section look like?
> 
> > while loop should have ended after the first iteration because gotsigchild
> > should have been set by the signal handler which executed before wait3()
> > even returned...
> 
> Setting gotsigchild > 0 would cause the while loop to continue, no?
> 

Right. Sorry for the noise.


Reply to: