Re: Question about execve.

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

 



> I tried the vfork.c test case on my c3750 with 32-bit kernel.  It
> didn't segv in a limited number of runs.  However, I did notice that
> getpid() is broken after vfork().

The vfork (clone) syscall corrupts (i.e., inserts wrong value)
the parent tid.  In the following, I disabled the printf's and
execve call in Carlos's testcase.  The child just does _exit().

The fast path through getpid is:

Dump of assembler code for function getpid:
0x0001ad2c <getpid+0>:	stw rp,-14(sp)
0x0001ad30 <getpid+4>:	mfctl tr3,r20
0x0001ad34 <getpid+8>:	ldw -414(r20),r19
0x0001ad38 <getpid+12>:	cmpib,>= 0,r19,0x1ad48 <getpid+28>
0x0001ad3c <getpid+16>:	copy r19,ret0
0x0001ad40 <getpid+20>:	ldw -14(sp),rp
0x0001ad44 <getpid+24>:	bv,n r0(rp)

Breakpoint 3, 0x0001ad34 in getpid ()
(gdb) del 2
(gdb) p/x $r20
$6 = 0x9a480

Breakpoint 4, main () at vfork.c:17
17	  child = vfork();
(gdb) x/x 0x9a480 - 0x414
0x9a06c:	0x00000000
(gdb) c
Continuing.

Breakpoint 3, 0x0001ad34 in getpid ()
(gdb) x/x 0x9a480 - 0x414
0x9a06c:	0x10101364

Breakpoint 4, main () at vfork.c:17
17	  child = vfork();
(gdb) x/64x 0x9a040
0x9a040:	0x00000000	0x00000000	0x00000000	0x00000000
0x9a050:	0x00000000	0x00000000	0x00000000	0x00000000
0x9a060:	0x00000000	0x00000000	0x00000000	0x00000000
0x9a070:	0x00000000	0x00000000	0x00000000	0x00000000
0x9a080:	0xc0521150	0x00000000	0x00000000	0x00000000

Breakpoint 3, 0x0001ad34 in getpid ()
(gdb) x/64x 0x9a040
0x9a040:	0x00000000	0x00000000	0x00000000	0x00000000
0x9a050:	0x00000000	0x00000000	0x00000000	0x00000000
0x9a060:	0x00000000	0x00000000	0x00000000	0x10101364
0x9a070:	0x00000000	0x00000000	0x00000000	0x00000000
0x9a080:	0xc03ae150	0x00000000	0x00000000	0x00000000

So, the only location changed by vfork is the parent tid.

dave@hiauly6:~$ strace ./vfork
execve("./vfork", ["./vfork"], [/* 16 vars */]) = 0
newuname({sys="Linux", node="hiauly6", ...}) = 0
brk(0)                                  = 0x9a000
brk(0x9acb4)                            = 0x9acb4
brk(0xbbcb4)                            = 0xbbcb4
brk(0xbc000)                            = 0xbc000
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x9a068) = 6212
fstat64(0x1, 0xc0258a08)                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000
write(1, "parent is 269488996\n", 20parent is 269488996
)   = 20
exit_group(0)                           = ?

(gdb) p/x 269488996
$1 = 0x10101364

I believe this is the "getpid" implementation:

static inline __attribute__((always_inline)) pid_t
really_getpid (pid_t oldval)
{
  if (__builtin_expect (oldval == 0, 1))
    {
      pid_t selftid = THREAD_GETMEM (THREAD_SELF, tid);
      if (__builtin_expect (selftid != 0, 1))
	return selftid;
     }

  INTERNAL_SYSCALL_DECL (err);
  pid_t result = INTERNAL_SYSCALL (getpid, err, 0);

  /* We do not set the PID field in the TID here since we might be
     called from a signal handler while the thread executes fork.  */
  if (oldval == 0)
    THREAD_SETMEM (THREAD_SELF, tid, result);
  return result;
}

As a side issue, gdb can't single step over mfctl instruction ;(

Dave
-- 
J. David Anglin                                  dave.anglin@xxxxxxxxxxxxxx
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)
--
To unsubscribe from this list: send the line "unsubscribe linux-parisc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux SoC]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux