]> sourceware.org Git - systemtap.git/commitdiff
Fixed PR16991 by avoiding an inifinte loop in task_dentry_path().
authorDavid Smith <dsmith@redhat.com>
Wed, 28 May 2014 15:54:57 +0000 (10:54 -0500)
committerDavid Smith <dsmith@redhat.com>
Wed, 28 May 2014 15:54:57 +0000 (10:54 -0500)
* tapset/linux/dentry.stp (task_dentry_path): Return "UNKNOWN" for
  unmounted synthetic filesystems.
* testsuite/systemtap.base/task_dentry_path.exp: New file.
* testsuite/systemtap.base/task_dentry_path.sh: Ditto.
* testsuite/systemtap.base/task_dentry_path.stp: Ditto.

tapset/linux/dentry.stp
testsuite/systemtap.base/task_dentry_path.exp [new file with mode: 0644]
testsuite/systemtap.base/task_dentry_path.sh [new file with mode: 0644]
testsuite/systemtap.base/task_dentry_path.stp [new file with mode: 0644]

index 0a564058c84e01e1c717bb40cf53f94368d08ec4..db3eba038ebfc2a38b100be2fba9d4242f469638 100644 (file)
@@ -170,6 +170,26 @@ function real_mount:long(vfsmnt:long)
  */
 function task_dentry_path:string(task:long,dentry:long,vfsmnt:long)
 {
+       /*
+        * There are various synthetic filesystems that never get
+        * mounted. Filesystems needing to implement special "root
+        * names" do so with dentry->d_op->d_dname(). Unfortunately,
+        * it isn't really safe for us to call
+        * dentry->d_op->d_dname(). We can't really validate the
+        * function pointer or know that it can be called safely in
+        * the current context.
+        *
+        * Some pseudo inodes are mountable.  When they are mounted,
+        * dentry == vfsmnt->mnt_root.  In that case, we'll just go
+        * ahead and handle them normally.
+        */
+       if (@defined(@cast(0, "dentry")->d_op->d_dname)
+           && @cast(dentry, "dentry")->d_op
+           && @cast(dentry, "dentry")->d_op->d_dname
+           && (!__dentry_IS_ROOT(dentry)
+               || dentry != @cast(vfsmnt, "vfsmount")->mnt_root))
+               return "UNKNOWN"
+
         root = & @cast(task, "task_struct")->fs->root
 
         while (1) {
diff --git a/testsuite/systemtap.base/task_dentry_path.exp b/testsuite/systemtap.base/task_dentry_path.exp
new file mode 100644 (file)
index 0000000..6e8d950
--- /dev/null
@@ -0,0 +1,16 @@
+# This testcase tests the fix for PR16991 - infinite loop in
+# task_dentry_path. When task_dentry_path hit a dentry from an
+# unmounted synthentic filesystem, it would go into an infinite loop
+# (until killed by MAXACTION).
+
+set test "task_dentry_path"
+spawn stap $srcdir/$subdir/$test.stp -c "sh $srcdir/$subdir/$test.sh"
+set ok 0
+expect {
+    -timeout 150
+    -re {ERROR.*MAXACTION} { incr ok; exp_continue }
+    timeout { fail "$test (timeout)" }
+    eof { }
+}
+catch {close}; catch {wait}
+if {$ok == 1} { fail "$test ($ok)" } { pass "$test ($ok)" }
diff --git a/testsuite/systemtap.base/task_dentry_path.sh b/testsuite/systemtap.base/task_dentry_path.sh
new file mode 100644 (file)
index 0000000..398600c
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+cd /tmp
+BASE="$(cd $(dirname ".")/../..; pwd -P)"
+echo $BASE
diff --git a/testsuite/systemtap.base/task_dentry_path.stp b/testsuite/systemtap.base/task_dentry_path.stp
new file mode 100644 (file)
index 0000000..7aeaec2
--- /dev/null
@@ -0,0 +1,18 @@
+global FSNOTIFY_EVENT_PATH = 1
+
+probe kernel.function("fsnotify") ?
+{
+    if (!target_set_pid(pid())) {
+       next
+    }
+    if ($data_is == FSNOTIFY_EVENT_PATH) {
+        path = task_dentry_path(task_current(), @cast($data, "path")->dentry,
+                               @cast($data, "path")->mnt);
+        println(path);
+    }
+}
+
+probe begin
+{
+    printf("begin\n")
+}
This page took 0.036009 seconds and 5 git commands to generate.