Bug 676474

Summary: nd_syscall.fork probe returns fork_kernel_thread for usespace forks
Product: [Fedora] Fedora Reporter: Josh Boyer <jwboyer>
Component: systemtapAssignee: Frank Ch. Eigler <fche>
Status: CLOSED CURRENTRELEASE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 14CC: dsmith, fche, jistone, mjw, roland, scox, wcohen
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-02-03 19:15:37 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Josh Boyer 2011-02-10 01:24:20 UTC
Description of problem:

On a 32-bit machine, running:

stap -v -e 'probe nd_syscall.fork{println(name)}'

results in systemtap printing 'fork_kernel_thread' for a userspace fork.

It seems that the script for fork looks at the regs to determine if the fork is for kernel or userspace by looking at regs->cs and seeing if any of the bottom bits are set.  When the tapset runs, it's not detecting the userspace fork.

Version-Release number of selected component (if applicable):

[jwboyer@r2d2 Desktop]$ rpm -q systemtap kernel kernel-devel
systemtap-1.3-3.fc14.i686
kernel-2.6.35.10-74.fc14.i686
kernel-devel-2.6.35.10-74.fc14.i686

How reproducible:

Always from what I can tell

Steps to Reproduce:
1. run stap -v -e 'probe nd_syscall.fork{println(name)}'
2. in another shell simply type 'ls'
3. watch the output happen
  
Actual results:

[root@r2d2 ~]# stap -v -e 'probe nd_syscall.fork{println(name)}'
Pass 1: parsed user script and 73 library script(s) using 22632virt/13240res/2260shr kb, in 580usr/20sys/608real ms.
Pass 2: analyzed script: 1 probe(s), 6 function(s), 20 embed(s), 0 global(s) using 23936virt/15156res/3136shr kb, in 2100usr/1750sys/3774real ms.
Pass 3: translated to C into "/tmp/stapvHODgx/stap_53cc33af0a00443aad4d8d4e0f8792c4_15471.c" using 23936virt/15416res/3396shr kb, in 10usr/0sys/4real ms.
Pass 4: compiled C into "stap_53cc33af0a00443aad4d8d4e0f8792c4_15471.ko" in 14230usr/2440sys/16671real ms.
Pass 5: starting run.
fork_kernel_thread
fork_kernel_thread
^CPass 5: run completed in 20usr/140sys/8417real ms.

Expected results:

tapset prints 'fork', 'vfork', or 'clone'. 

Additional info:

I don't seem to hit this issue on x86_64.  Also, if you do:

cd /usr/share/systemtap/testsuite
make installcheck RUNTESTFLAGS="nd_syscall.exp"

the forkwait test fails, among others:

[root@r2d2 testsuite]# make installcheck RUNTESTFLAGS="nd_syscall.exp"
Making a new site.exp file...
make  check-DEJAGNU RUNTESTFLAGS="nd_syscall.exp --tool_opts \'install \'"
make[1]: Entering directory `/usr/share/systemtap/testsuite'
srcdir=`CDPATH="${ZSH_VERSION+.}:" && cd . && pwd`; export srcdir; \
EXPECT=expect; export EXPECT; \
runtest="env SYSTEMTAP_TESTAPPS= SYSTEMTAP_RUNTIME=/usr/share/systemtap/runtime SYSTEMTAP_TAPSET=/usr/share/systemtap/tapset LD_LIBRARY_PATH=/usr/lib/systemtap CRASH_LIBDIR=/usr/lib/systemtap PATH=/usr/bin:$PATH SYSTEMTAP_PATH=/usr/bin SYSTEMTAP_INCLUDES=/usr/include  PKGLIBDIR=/usr/libexec/systemtap ./execrc runtest"; \
if /bin/sh -c "$runtest --version" > /dev/null 2>&1; then \
  exit_status=0; l='systemtap'; for tool in $l; do \
    if $runtest  --tool $tool --tool_opts \'\' --srcdir $srcdir nd_syscall.exp --tool_opts \'install \'; \
    then :; else exit_status=1; fi; \
  done; \
else echo "WARNING: could not find \`runtest'" 1>&2; :;\
fi; \
exit $exit_status
WARNING: Couldn't find the global config file.
kernel location: 
kernel version: 2.6.35.10-74.fc14.i686
systemtap location: /usr/bin/stap
systemtap version: version 1.3/0.151 non-git sources
gcc location: /usr/bin/gcc
gcc version: gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)
Test Run By root on Wed Feb  9 20:19:55 2011
Native configuration is i686-pc-linux-gnu

		=== systemtap tests ===

Schedule of variations:
    unix

Running target unix
Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target.
Using /usr/share/dejagnu/config/unix.exp as generic interface file for target.
Using /usr/share/systemtap/testsuite/config/unix.exp as tool-and-target-specific interface file.

Host: Linux r2d2 2.6.35.10-74.fc14.i686 #1 SMP Thu Dec 23 16:17:40 UTC 2010 i686 i686 i386 GNU/Linux
Snapshot: version 1.3/0.151 non-git sources
GCC: 4.5.1 [gcc (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4)]
Distro: Fedora release 14 (Laughlin)

Running /usr/share/systemtap/testsuite/systemtap.syscall/nd_syscall.exp ...
FAIL: 32-bit dup nd_syscall
FAIL: 32-bit eventfd nd_syscall
FAIL: 32-bit forkwait nd_syscall
FAIL: 32-bit inotify nd_syscall
FAIL: 32-bit net1 nd_syscall
FAIL: 32-bit pipe nd_syscall
FAIL: 32-bit poll nd_syscall
FAIL: 32-bit signalfd nd_syscall

		=== systemtap Summary ===

# of expected passes		27
# of unexpected failures	8
make[1]: Leaving directory `/usr/share/systemtap/testsuite'
if test -n ""; then mail  < systemtap.sum; fi
[root@r2d2 testsuite]#

Comment 1 Roland McGrath 2011-02-10 03:40:23 UTC
I don't have a 32-bit setup handy.  Can you show the output from:

stap -v -e 'probe nd_syscall.fork{printf("%s cs=%#x\n", name, @cast(regs, "pt_regs")->cs)}'

?

Comment 2 Roland McGrath 2011-02-10 03:45:41 UTC
Also please try version 1.4 from updates-testing.

Comment 3 Roland McGrath 2011-02-10 06:26:08 UTC
Reproduced with systemtap-1.4-2.fc14.i686 on 2.6.35.10-74.fc14.i686

stap -v -e 'probe kernel.function("do_fork") {printf("regs=%p cs=%#x ip=%#x orig_ax=%#x\n", $regs, $regs->cs, $regs->ip, $regs->orig_ax)} probe nd_syscall.fork{printf("%s regs=%p\n", name, regs) }'

shows correct result from $regs in function probe but wrong result (all zeros) at nd_syscall.fork probe, i.e. kprobe.function probe, differing regs value.

Adding manual probe kprobe.function("do_fork") { printf("regs=%p\n", pointer_arg(3)) }' shows the right result.

do_fork is not asmlinkage, asmlinkage() in nd_syscalls.stp:nd_syscall.fork is wrong.

Comment 4 Roland McGrath 2011-02-10 06:30:40 UTC
Should be fixed upstream by commit e00876c, not tested.

Comment 5 Josh Boyer 2011-02-10 13:23:14 UTC
(In reply to comment #4)
> Should be fixed upstream by commit e00876c, not tested.

That's an easy enough change to test locally.  I removed asmlinkage from do_fork in the nd_syscall.stp tapset on my machine and reran the simple testcase.  It does what I would expect:

[root@r2d2 testsuite]# stap -v -e 'probe nd_syscall.fork{println(name)}'
Pass 1: parsed user script and 73 library script(s) using 22216virt/13068res/2248shr kb, in 570usr/60sys/663real ms.
Pass 2: analyzed script: 1 probe(s), 5 function(s), 20 embed(s), 0 global(s) using 23048virt/14636res/3012shr kb, in 130usr/1810sys/2828real ms.
Pass 3: translated to C into "/tmp/stap1fzO3q/stap_9fdccdaf7710f055358ef93a11c15f3a_15392.c" using 23156virt/14892res/3136shr kb, in 0usr/0sys/8real ms.
Pass 4: compiled C into "stap_9fdccdaf7710f055358ef93a11c15f3a_15392.ko" in 5450usr/1350sys/7268real ms.
Pass 5: starting run.
fork
fork
^?^CPass 5: run completed in 20usr/170sys/9950real ms.
[root@r2d2 testsuite]# 

The forkwait test in the testsuite also passes now. The rest of the FAIL cases are still present, but that isn't because of this specific issue.

Thanks for the quick resolution!

Comment 6 Frank Ch. Eigler 2012-02-03 19:15:37 UTC
fix present in 1.5+