summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Teo <eteo@redhat.com>2010-02-04 13:42:24 -0500
committerFrank Ch. Eigler <fche@elastic.org>2010-02-04 13:42:24 -0500
commitecf33ff44feaccfde06f3c2b55b0a78d69e29545 (patch)
treea02d27bba7e2860db4281e64daf4d1883c463cc3
parent8155cc835adb286c456f30ebaa961508bc064e90 (diff)
downloadsystemtap-steved-ecf33ff44feaccfde06f3c2b55b0a78d69e29545.tar.gz
systemtap-steved-ecf33ff44feaccfde06f3c2b55b0a78d69e29545.tar.xz
systemtap-steved-ecf33ff44feaccfde06f3c2b55b0a78d69e29545.zip
new sample: pfiles
-rw-r--r--testsuite/systemtap.examples/index.html6
-rw-r--r--testsuite/systemtap.examples/index.txt17
-rw-r--r--testsuite/systemtap.examples/keyword-index.html14
-rw-r--r--testsuite/systemtap.examples/keyword-index.txt27
-rw-r--r--testsuite/systemtap.examples/process/pfiles.meta6
-rwxr-xr-xtestsuite/systemtap.examples/process/pfiles.stp606
6 files changed, 651 insertions, 25 deletions
diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html
index eaf21135..1c16d37b 100644
--- a/testsuite/systemtap.examples/index.html
+++ b/testsuite/systemtap.examples/index.html
@@ -91,9 +91,6 @@ keywords: <a href="keyword-index.html#IO">IO</a> <br>
<li><a href="io/mbrwatch.stp">io/mbrwatch.stp</a> - Monitor read/write of MBR (boot sector) area of block devices<br>
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#MONITORING">MONITORING</a> <br>
<p> The mbrwatch.stp script reports any attempted reads/writes of the first few sectors of a raw block device.</p></li>
-<li><a href="io/nfs_func_log.stp">io/nfs_func_log.stp</a> - Print Log of NFS Functions Used<br>
-keywords: <a href="keyword-index.html#IO">IO</a> <br>
-<p>The nfs_func_log.stp script logs the uses of NFS functions in the kernel. The output is a trace. Each line contains the time stamp, the process name, and the process number followed by the function name.</p></li>
<li><a href="io/nfs_func_users.stp">io/nfs_func_users.stp</a> - Tally the Number of NFS Functions Used by Each Process<br>
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <br>
<p>The nfs_func_users.stp script counts the uses of NFS functions in the kernel on a per process bases. The output is sorted from the process with the greatest number of NFS functions called to the least. The output contains the executable name, the process number, and the total number of NFS functions called by the process.</p></li>
@@ -187,6 +184,9 @@ keywords: <a href="keyword-index.html#SCHEDULER">SCHEDULER</a> <br>
<li><a href="process/pf2.stp">process/pf2.stp</a> - Profile kernel functions<br>
keywords: <a href="keyword-index.html#PROFILING">PROFILING</a> <br>
<p>The pf2.stp script sets up time-based sampling. Every five seconds it prints out a sorted list with the top ten kernel functions with samples.</p></li>
+<li><a href="process/pfiles.stp">process/pfiles.stp</a> - print process file descriptors<br>
+keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#FILES">FILES</a> <br>
+<p>Run pfiles.stp to produce a human-readable summary of all open file descriptors of a given process. Specify the process-id as -x PID for fastest performance.</p></li>
<li><a href="process/plimit.stp">process/plimit.stp</a> - print resource limits<br>
keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <br>
<p>The script prints a variety of resource limits for a given pid, like /proc/$$/limits on recent kernels.</p></li>
diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt
index 9a3637ae..908db615 100644
--- a/testsuite/systemtap.examples/index.txt
+++ b/testsuite/systemtap.examples/index.txt
@@ -156,15 +156,6 @@ keywords: io monitoring
first few sectors of a raw block device.
-io/nfs_func_log.stp - Print Log of NFS Functions Used
-keywords: io
-
- The nfs_func_log.stp script logs the uses of NFS functions in the
- kernel. The output is a trace. Each line contains the time stamp,
- the process name, and the process number followed by the function
- name.
-
-
io/nfs_func_users.stp - Tally the Number of NFS Functions Used by Each Process
keywords: io profiling
@@ -463,6 +454,14 @@ keywords: profiling
samples.
+process/pfiles.stp - print process file descriptors
+keywords: process files
+
+ Run pfiles.stp to produce a human-readable summary of all open file
+ descriptors of a given process. Specify the process-id as -x PID for
+ fastest performance.
+
+
process/plimit.stp - print resource limits
keywords: process
diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html
index ef1a801f..56119081 100644
--- a/testsuite/systemtap.examples/keyword-index.html
+++ b/testsuite/systemtap.examples/keyword-index.html
@@ -39,7 +39,7 @@
</ul>
<h2>Examples by Keyword</h2>
-<p><tt><a href="#ALLOCATOR">ALLOCATOR</a> <a href="#AUTOFS">AUTOFS</a> <a href="#BACKTRACE">BACKTRACE</a> <a href="#BUFFER">BUFFER</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DEVICE">DEVICE</a> <a href="#DISK">DISK</a> <a href="#FILESYSTEM">FILESYSTEM</a> <a href="#FORMAT">FORMAT</a> <a href="#FREE">FREE</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#HACK">HACK</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#MONITOR">MONITOR</a> <a href="#MONITORING">MONITORING</a> <a href="#NETWORK">NETWORK</a> <a href="#NFS">NFS</a> <a href="#NUMA">NUMA</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROCESS">PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SCSI">SCSI</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLAB">SLAB</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#STATISTICS">STATISTICS</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRACEPOINT">TRACEPOINT</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#TTY">TTY</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
+<p><tt><a href="#ALLOCATOR">ALLOCATOR</a> <a href="#AUTOFS">AUTOFS</a> <a href="#BACKTRACE">BACKTRACE</a> <a href="#BUFFER">BUFFER</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DEVICE">DEVICE</a> <a href="#DISK">DISK</a> <a href="#FILES">FILES</a> <a href="#FILESYSTEM">FILESYSTEM</a> <a href="#FORMAT">FORMAT</a> <a href="#FREE">FREE</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#HACK">HACK</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#MONITOR">MONITOR</a> <a href="#MONITORING">MONITORING</a> <a href="#NETWORK">NETWORK</a> <a href="#NFS">NFS</a> <a href="#NUMA">NUMA</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROCESS">PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SCSI">SCSI</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLAB">SLAB</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#STATISTICS">STATISTICS</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRACEPOINT">TRACEPOINT</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#TTY">TTY</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p>
<h3><a name="ALLOCATOR">ALLOCATOR</a></h3>
<ul>
<li><a href="memory/vm.tracepoints.stp">memory/vm.tracepoints.stp</a> - Collect slab allocation statistics<br>
@@ -100,6 +100,12 @@ keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html
keywords: <a href="keyword-index.html#DISK">DISK</a> <br>
<p>Get the status of reading/writing disk every 5 seconds, output top ten entries during that period.</p></li>
</ul>
+<h3><a name="FILES">FILES</a></h3>
+<ul>
+<li><a href="process/pfiles.stp">process/pfiles.stp</a> - print process file descriptors<br>
+keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#FILES">FILES</a> <br>
+<p>Run pfiles.stp to produce a human-readable summary of all open file descriptors of a given process. Specify the process-id as -x PID for fastest performance.</p></li>
+</ul>
<h3><a name="FILESYSTEM">FILESYSTEM</a></h3>
<ul>
<li><a href="general/badname.stp">general/badname.stp</a> - Bad Filename Filter<br>
@@ -183,9 +189,6 @@ keywords: <a href="keyword-index.html#IO">IO</a> <br>
<li><a href="io/mbrwatch.stp">io/mbrwatch.stp</a> - Monitor read/write of MBR (boot sector) area of block devices<br>
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#MONITORING">MONITORING</a> <br>
<p> The mbrwatch.stp script reports any attempted reads/writes of the first few sectors of a raw block device.</p></li>
-<li><a href="io/nfs_func_log.stp">io/nfs_func_log.stp</a> - Print Log of NFS Functions Used<br>
-keywords: <a href="keyword-index.html#IO">IO</a> <br>
-<p>The nfs_func_log.stp script logs the uses of NFS functions in the kernel. The output is a trace. Each line contains the time stamp, the process name, and the process number followed by the function name.</p></li>
<li><a href="io/nfs_func_users.stp">io/nfs_func_users.stp</a> - Tally the Number of NFS Functions Used by Each Process<br>
keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <br>
<p>The nfs_func_users.stp script counts the uses of NFS functions in the kernel on a per process bases. The output is sorted from the process with the greatest number of NFS functions called to the least. The output contains the executable name, the process number, and the total number of NFS functions called by the process.</p></li>
@@ -324,6 +327,9 @@ keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-inde
<li><a href="process/forktracker.stp">process/forktracker.stp</a> - Trace Creation of Processes<br>
keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#SCHEDULER">SCHEDULER</a> <br>
<p>The forktracker.stp script prints out a time-stamped entry showing each fork and exec operation on the machine. This can be useful to determine what process is creating a flurry of short-lived processes.</p></li>
+<li><a href="process/pfiles.stp">process/pfiles.stp</a> - print process file descriptors<br>
+keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#FILES">FILES</a> <br>
+<p>Run pfiles.stp to produce a human-readable summary of all open file descriptors of a given process. Specify the process-id as -x PID for fastest performance.</p></li>
<li><a href="process/plimit.stp">process/plimit.stp</a> - print resource limits<br>
keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <br>
<p>The script prints a variety of resource limits for a given pid, like /proc/$$/limits on recent kernels.</p></li>
diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt
index 0f1c5885..b4ff7307 100644
--- a/testsuite/systemtap.examples/keyword-index.txt
+++ b/testsuite/systemtap.examples/keyword-index.txt
@@ -118,6 +118,16 @@ keywords: disk
ten entries during that period.
+= FILES =
+
+process/pfiles.stp - print process file descriptors
+keywords: process files
+
+ Run pfiles.stp to produce a human-readable summary of all open file
+ descriptors of a given process. Specify the process-id as -x PID for
+ fastest performance.
+
+
= FILESYSTEM =
general/badname.stp - Bad Filename Filter
@@ -311,15 +321,6 @@ keywords: io monitoring
first few sectors of a raw block device.
-io/nfs_func_log.stp - Print Log of NFS Functions Used
-keywords: io
-
- The nfs_func_log.stp script logs the uses of NFS functions in the
- kernel. The output is a trace. Each line contains the time stamp,
- the process name, and the process number followed by the function
- name.
-
-
io/nfs_func_users.stp - Tally the Number of NFS Functions Used by Each Process
keywords: io profiling
@@ -681,6 +682,14 @@ keywords: process scheduler
determine what process is creating a flurry of short-lived processes.
+process/pfiles.stp - print process file descriptors
+keywords: process files
+
+ Run pfiles.stp to produce a human-readable summary of all open file
+ descriptors of a given process. Specify the process-id as -x PID for
+ fastest performance.
+
+
process/plimit.stp - print resource limits
keywords: process
diff --git a/testsuite/systemtap.examples/process/pfiles.meta b/testsuite/systemtap.examples/process/pfiles.meta
new file mode 100644
index 00000000..f5b623ce
--- /dev/null
+++ b/testsuite/systemtap.examples/process/pfiles.meta
@@ -0,0 +1,6 @@
+title: print process file descriptors
+name: pfiles.stp
+keywords: process files
+description: Run pfiles.stp to produce a human-readable summary of all open file descriptors of a given process. Specify the process-id as -x PID for fastest performance.
+test_check: stap -gp4 pfiles.stp -x $$
+test_installcheck: stap -g pfiles.stp -x $$
diff --git a/testsuite/systemtap.examples/process/pfiles.stp b/testsuite/systemtap.examples/process/pfiles.stp
new file mode 100755
index 00000000..8ac90c64
--- /dev/null
+++ b/testsuite/systemtap.examples/process/pfiles.stp
@@ -0,0 +1,606 @@
+#! /usr/bin/stap -g
+# pfiles
+# Copyright (C) 2007-2010 Red Hat, Inc., Eugene Teo <eteo@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# pfiles report information for all open files by the process id.
+#
+# pfiles is not a port of Solaris' pfiles tool. It was written based on the
+# example outputs in:
+# - https://bugzilla.redhat.com/show_bug.cgi?id=223489
+# - http://blogs.sun.com/peteh/entry/pfiles_1_locked_files_and
+# - http://lists.samba.org/archive/samba-technical/2001-May/014293.html
+# - http://mail.gnome.org/archives/gconf-list/2004-December/msg00005.html
+#
+# systemtap SNAPSHOT c9116e9980ad6e417697737f8d54a4a625811245
+# on kernel 2.6.18-128.1.13.el5
+# and on kernel 2.6.27.21-170.2.56.fc10.i686.PAE
+#
+# Last updated: Thu May 28 20:37:57 SGT 2009
+#
+# pfiles is able to:
+# - report locked open files
+# - report pathname information
+# - report socket information (thanks Luis Henriques)
+# - report sk_userlocks (thanks Arnaldo Carvalho de Melo)
+# - report socket options
+#
+# Example:
+# $ ./pfiles.stp `pgrep udevd`
+# 787: udevd
+# Current rlimit: 32 file descriptors
+# 0: S_IFCHR mode:0666 dev:0,15 ino:396 uid:0 gid:0 rdev:1,3
+# O_RDWR|O_LARGEFILE
+# /dev/null
+# 1: S_IFCHR mode:0666 dev:0,15 ino:396 uid:0 gid:0 rdev:1,3
+# O_RDWR|O_LARGEFILE
+# /dev/null
+# 2: S_IFCHR mode:0666 dev:0,15 ino:396 uid:0 gid:0 rdev:1,3
+# O_RDWR|O_LARGEFILE
+# /dev/null
+# 3: S_IFDIR mode:0600 dev:0,9 ino:1 uid:0 gid:0 rdev:0,0
+# O_RDONLY
+# inotify
+# 4: S_IFSOCK mode:0777 dev:0,4 ino:2353 uid:0 gid:0 rdev:0,0
+# O_RDWR
+# socket:[2353]
+# SO_PASSCRED,SO_TYPE(2),SO_SNDBUF(111616),SO_RCVBUF(111616)
+# sockname: AF_UNIX
+# 5: S_IFSOCK mode:0777 dev:0,4 ino:2354 uid:0 gid:0 rdev:0,0
+# O_RDWR
+# socket:[2354]
+# SO_TYPE(2),SO_SNDBUF(111616),SO_RCVBUF(33554432)
+# ulocks: rcv
+# 6: S_IFIFO mode:0600 dev:0,6 ino:2355 uid:0 gid:0 rdev:0,0
+# O_RDONLY|O_NONBLOCK
+# pipe:[2355]
+# 7: S_IFIFO mode:0600 dev:0,6 ino:2355 uid:0 gid:0 rdev:0,0
+# O_WRONLY|O_NONBLOCK
+# pipe:[2355]
+#
+# I used Andrew Tridgell's locktst.c to test the advisory lock code.
+# You can download it at http://samba.org/ftp/unpacked/junkcode/locktst.c
+#
+# $ ./locktst file &
+# fcntl_lock 3 6 1 1 1
+# $ pfiles 10126 | grep advisory -A1 -B2
+# 3: S_IFREG mode:0644 dev:253,0 ino:15237159 uid:500 gid:500 rdev:0,0
+# O_RDWR
+# advisory write lock set by process 10126
+# /home/eteo/pfiles/file
+#
+
+%{
+#include <linux/file.h>
+#include <net/sock.h>
+#include <linux/un.h>
+%}
+
+function task_valid_file_handle:long (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ if (!filp) {
+ THIS->__retvalue = 0;
+ rcu_read_unlock();
+ return;
+ }
+ THIS->__retvalue = (long)filp;
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function i_mode2str:string (i_mode:long) %{ /* pure */
+ snprintf(THIS->__retvalue, MAXSTRINGLEN, "%d", (int)THIS->i_mode);
+ THIS->i_mode = simple_strtol(THIS->__retvalue, NULL, 10);
+
+ if (S_ISLNK(THIS->i_mode)) strlcpy (THIS->__retvalue, "S_IFLNK", MAXSTRINGLEN);
+ else if (S_ISREG(THIS->i_mode)) strlcpy (THIS->__retvalue, "S_IFREG", MAXSTRINGLEN);
+ else if (S_ISDIR(THIS->i_mode)) strlcpy (THIS->__retvalue, "S_IFDIR", MAXSTRINGLEN);
+ else if (S_ISCHR(THIS->i_mode)) strlcpy (THIS->__retvalue, "S_IFCHR", MAXSTRINGLEN);
+ else if (S_ISBLK(THIS->i_mode)) strlcpy (THIS->__retvalue, "S_IFBLK", MAXSTRINGLEN);
+ else if (S_ISFIFO(THIS->i_mode)) strlcpy (THIS->__retvalue, "S_IFIFO", MAXSTRINGLEN);
+ else if (S_ISSOCK(THIS->i_mode)) strlcpy (THIS->__retvalue, "S_IFSOCK", MAXSTRINGLEN);
+%}
+
+function task_file_handle_i_mode:long (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ THIS->__retvalue = kread(&filp->f_dentry->d_inode->i_mode);
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_majmin_dev:string (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+ int dev_nr;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ dev_nr = kread(&filp->f_dentry->d_inode->i_sb->s_dev);
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ "%d,%d", MAJOR(dev_nr), MINOR(dev_nr));
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_majmin_rdev:string (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+ int rdev_nr;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ rdev_nr = kread(&filp->f_dentry->d_inode->i_rdev);
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ "%d,%d", MAJOR(rdev_nr), MINOR(rdev_nr));
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_i_node:long (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ THIS->__retvalue = kread(&filp->f_dentry->d_inode->i_ino);
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_uid:long (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+ /* git commit d76b0d9b */
+ THIS->__retvalue = kread(&filp->f_cred->fsuid);
+#else
+ THIS->__retvalue = kread(&filp->f_uid);
+#endif
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_gid:long (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+ /* git commit d76b0d9b */
+ THIS->__retvalue = kread(&filp->f_cred->fsgid);
+#else
+ THIS->__retvalue = kread(&filp->f_gid);
+#endif
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_f_flags:long (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ THIS->__retvalue = kread(&filp->f_flags);
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_fd_flags:string (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct fdtable *fdt;
+ int gcoe;
+
+ rcu_read_lock();
+ fdt = files_fdtable(files);
+ gcoe = FD_ISSET(THIS->fd, kread(&fdt->close_on_exec));
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ "%s", gcoe ? "FD_CLOEXEC" : "");
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_flock:string (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct file_lock *flock;
+ int fl_type, fl_pid;
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ flock = kread(&filp->f_dentry->d_inode->i_flock);
+ fl_type = fl_pid = -1;
+ if (flock) {
+ fl_type = kread(&flock->fl_type);
+ fl_pid = kread(&flock->fl_pid);
+ }
+
+ if (fl_type != -1) /* !flock */
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ " advisory %s lock set by process %d",
+ fl_type ? "write" : "read", fl_pid);
+ else
+ snprintf(THIS->__retvalue, MAXSTRINGLEN, "NULL");
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_d_path:string (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ char *page = (char *)__get_free_page(GFP_KERNEL);
+ struct file *filp;
+ struct dentry *dentry;
+ struct vfsmount *vfsmnt;
+
+ /* TODO: handle !page */
+ if (!page)
+ return;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ dentry = kread(&filp->f_dentry);
+ vfsmnt = kread(&filp->f_vfsmnt);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+ /* git commit 9d1bc601 */
+ snprintf(THIS->__retvalue, MAXSTRINGLEN, "%s",
+ d_path(&filp->f_path, page, PAGE_SIZE));
+#else
+ snprintf(THIS->__retvalue, MAXSTRINGLEN, "%s",
+ d_path(dentry, vfsmnt, page, PAGE_SIZE));
+#endif
+ free_page((unsigned long)page);
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function task_file_handle_socket:long (task:long, fd:long) %{ /* pure */
+ struct task_struct *p = (struct task_struct *)((long)THIS->task);
+ struct files_struct *files = kread(&p->files);
+ struct inode *inode;
+ struct file *filp;
+
+ rcu_read_lock();
+ filp = fcheck_files(files, THIS->fd);
+ if (!filp) {
+ THIS->__retvalue = 0;
+ rcu_read_unlock();
+ return;
+ }
+ inode = kread(&filp->f_dentry->d_inode);
+ if (S_ISSOCK(kread(&inode->i_mode)))
+ THIS->__retvalue = (long)SOCKET_I(inode);
+ rcu_read_unlock();
+
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_userlocks:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ struct sock *sk = (struct sock *)kread(&sock->sk);
+ unsigned char locks = sk->sk_userlocks;
+ int printed = 0;
+
+ THIS->__retvalue[0] = '\0';
+
+ if (locks & SOCK_RCVBUF_LOCK)
+ printed = snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ "ulocks: rcv");
+
+ if (locks & SOCK_SNDBUF_LOCK)
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ "ulocks: %ssnd",
+ printed ? "rcv, " : "");
+
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_optname:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ int optval;
+ int optlen;
+ int ret, a;
+ char str[30];
+ struct linger ling;
+ struct optname_item {
+ int optnum;
+ const char *optname;
+ int show_val;
+ } *p;
+ struct optname_item optname_entries[] = {
+ { SO_DEBUG, "SO_DEBUG", 0 },
+ { SO_REUSEADDR, "SO_REUSEADDR", 0 },
+ { SO_DONTROUTE, "SO_DONTROUTE", 0 },
+ { SO_BROADCAST, "SO_BROADCAST", 0 },
+ { SO_KEEPALIVE, "SO_KEEPALIVE", 0 },
+ { SO_OOBINLINE, "SO_OOBINLINE", 0 },
+ { SO_PASSCRED, "SO_PASSCRED", 0 },
+/* { SO_SNDLOWAT, "SO_SNDLOWAT", 0 },*/
+ { SO_TYPE, "SO_TYPE", 1 },
+ { SO_ERROR, "SO_ERROR", 1 },
+ { SO_SNDBUF, "SO_SNDBUF", 1 },
+ { SO_RCVBUF, "SO_RCVBUF", 1 },
+ { SO_NO_CHECK, "SO_NO_CHECK", 1 },
+ { 0, NULL, 0 },
+ };
+
+ for (p = optname_entries; p->optname; ++p) {
+ optlen = sizeof(optval);
+ ret = kernel_getsockopt(sock, SOL_SOCKET, p->optnum, (char *)&optval, &optlen);
+ if (ret == 0 && optval != 0) {
+ if (!p->show_val)
+ snprintf(str, MAXSTRINGLEN, "%s,", p->optname);
+ else
+ snprintf(str, MAXSTRINGLEN, "%s(%d),", p->optname, optval);
+ strcat(THIS->__retvalue, str);
+ }
+ }
+
+ optlen = sizeof(ling);
+ ret = kernel_getsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&ling, &optlen);
+ if (ret == 0 && ling.l_onoff != 0) {
+ snprintf(str, MAXSTRINGLEN, "SO_LINGER(%d),", ling.l_linger);
+ strcat(THIS->__retvalue, str);
+ }
+
+ THIS->__retvalue[strlen(THIS->__retvalue) - 1] = '\0';
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_family:long (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ THIS->__retvalue = (long)kread(&sock->ops->family);
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_unix_sockname:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ struct sockaddr_un un_addr;
+ int err, len;
+
+ err = sock->ops->getname(sock, (struct sockaddr *)(&un_addr), &len, 0);
+// err = kernel_getsockname(kread(&sock), (struct sockaddr *)(&un_addr), &len);
+ if (!err) {
+ if (kread(&un_addr.sun_path[0]) != 0)
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ " sockname: AF_UNIX %s", un_addr.sun_path);
+ else
+ snprintf(THIS->__retvalue, MAXSTRINGLEN, " sockname: AF_UNIX");
+ }
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_unix_peername:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ struct sockaddr_un un_addr;
+ int err, len;
+
+ err = sock->ops->getname(sock, (struct sockaddr *)(&un_addr), &len, 1);
+// err = kernel_getpeername(kread(&sock), (struct sockaddr *)(&un_addr), &len);
+ if (!err) {
+ if (kread(&un_addr.sun_path[0]) != 0)
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ " peername: AF_UNIX %s", un_addr.sun_path);
+ else
+ snprintf(THIS->__retvalue, MAXSTRINGLEN, " peername: AF_UNIX");
+ }
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_ipv4_sockname:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ struct sockaddr_in in_addr;
+ __be32 addr, port;
+ int err, len;
+
+ err = sock->ops->getname (sock, (struct sockaddr*)(&in_addr), &len, 0);
+ if (!err) {
+ addr = kread(&in_addr.sin_addr.s_addr);
+ port = htons(kread(&in_addr.sin_port));
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ " sockname: AF_INET " NIPQUAD_FMT " port: %d",
+ NIPQUAD(addr), port);
+ }
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_ipv4_peername:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ struct sockaddr_in in_addr;
+ __be32 addr, port;
+ int err, len;
+
+ err = sock->ops->getname (sock, (struct sockaddr*)(&in_addr), &len, 1);
+ if (!err) {
+ addr = kread(&in_addr.sin_addr.s_addr);
+ port = htons(kread(&in_addr.sin_port));
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ " peername: AF_INET " NIPQUAD_FMT " port: %d",
+ NIPQUAD(addr), port);
+ }
+ CATCH_DEREF_FAULT();
+%}
+
+%{
+#ifndef NIP6_FMT
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#endif
+#ifndef NIP6
+#define NIP6(addr) \
+ ntohs((addr).s6_addr16[0]), \
+ ntohs((addr).s6_addr16[1]), \
+ ntohs((addr).s6_addr16[2]), \
+ ntohs((addr).s6_addr16[3]), \
+ ntohs((addr).s6_addr16[4]), \
+ ntohs((addr).s6_addr16[5]), \
+ ntohs((addr).s6_addr16[6]), \
+ ntohs((addr).s6_addr16[7])
+#endif
+
+%}
+
+function socket_ipv6_sockname:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ struct sockaddr_in6 in_addr;
+ __be32 port;
+ int err, len;
+
+ err = sock->ops->getname (sock, (struct sockaddr*)(&in_addr), &len, 0);
+ if (!err) {
+ port = htons(kread(&in_addr.sin6_port));
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ " sockname: AF_INET6 " NIP6_FMT " port: %d",
+ NIP6(in_addr.sin6_addr), port);
+ }
+ CATCH_DEREF_FAULT();
+%}
+
+function socket_ipv6_peername:string (sock:long) %{ /* pure */
+ struct socket *sock = (struct socket *)((long)THIS->sock);
+ struct sockaddr_in6 in_addr;
+ __be32 port;
+ int err, len;
+
+ err = sock->ops->getname (sock, (struct sockaddr*)(&in_addr), &len, 1);
+ if (!err) {
+ port = htons(kread(&in_addr.sin6_port));
+ snprintf(THIS->__retvalue, MAXSTRINGLEN,
+ " peername: AF_INET6 " NIP6_FMT " port: %d",
+ NIP6(in_addr.sin6_addr), port);
+ }
+ CATCH_DEREF_FAULT();
+%}
+
+function print_file_handle_general(task, fd) {
+ printf("%4d: %s mode:%04o dev:%s ino:%d uid:%d gid:%d rdev:%s\n",
+ fd, i_mode2str(task_file_handle_i_mode(task, fd)),
+ task_file_handle_i_mode(task, fd) & 0777,
+ task_file_handle_majmin_dev(task, fd),
+ task_file_handle_i_node(task, fd),
+ task_file_handle_uid(task, fd),
+ task_file_handle_gid(task, fd),
+ task_file_handle_majmin_rdev(task, fd));
+}
+
+function print_file_handle_flags(task, fd) {
+ printf(" %s %s\n",
+ _sys_open_flag_str(task_file_handle_f_flags(task, fd)),
+ task_file_handle_fd_flags(task, fd));
+}
+
+function print_file_handle_flock(task, fd) {
+ flock = task_file_handle_flock(task, fd)
+ if (!isinstr(flock, "NULL"))
+ printf("%s\n", flock)
+}
+
+function print_file_handle_d_path(task, fd) {
+ printf(" %s\n", task_file_handle_d_path(task, fd))
+}
+
+function print_socket_userlocks(sock) {
+ slocks = socket_userlocks(sock)
+ if (strlen(slocks) > 0)
+ printf(" %s\n", slocks)
+}
+
+function print_unix_socket(sock) {
+ sockname = socket_unix_sockname(sock)
+ peername = socket_unix_peername(sock)
+ printf("%s%s", strlen(sockname) > 0 ? sockname . "\n" : "",
+ strlen(peername) > 0 ? peername . "\n" : "")
+}
+
+function print_ipv4_socket(sock) {
+ sockname = socket_ipv4_sockname(sock)
+ peername = socket_ipv4_peername(sock)
+ printf("%s%s", strlen(sockname) > 0 ? sockname . "\n" : "",
+ strlen(peername) > 0 ? peername . "\n" : "")
+}
+
+function print_ipv6_socket(sock) {
+ sockname = socket_ipv6_sockname(sock)
+ peername = socket_ipv6_peername(sock)
+ printf("%s%s", strlen(sockname) > 0 ? sockname . "\n" : "",
+ strlen(peername) > 0 ? peername . "\n" : "")
+}
+
+function print_socket_optname(sock) {
+ str = socket_optname(sock)
+ printf(" %s", strlen(str) > 0 ? str . "\n" : "")
+}
+
+probe begin {
+%( $# < 1
+ %? pid = target()
+ %: pid = $1
+%)
+ # if (pid == 0) error ("Please provide valid target process-id as $1 or -x PID");
+ task = pid2task(pid)
+ if (task == 0) error (sprintf("Process-id %d is invalid, please provide valid PID as $1 or -x PID", pid))
+
+ max_fds = task_max_file_handles(task)
+
+ printf("%6d: %s\n", pid, pid2execname(pid))
+ printf(" Current rlimit: %d file descriptors\n", max_fds)
+
+ for (fd = 0; fd < max_fds; fd++) {
+ if (task_valid_file_handle(task, fd)) {
+ print_file_handle_general(task, fd)
+ print_file_handle_flags(task, fd)
+ print_file_handle_flock(task, fd)
+ print_file_handle_d_path(task, fd)
+ sock = task_file_handle_socket(task, fd)
+ if (sock) {
+ print_socket_optname(sock)
+ fam = socket_family(sock)
+ if (fam == 1) { /* AF_UNIX */
+ print_unix_socket(sock)
+ } else if (fam == 2) { /* AF_INET */
+ print_ipv4_socket(sock)
+ } else if (fam == 10) { /* AF_INET6 */
+ print_ipv6_socket(sock)
+ }
+ print_socket_userlocks(sock)
+ }
+ }
+ }
+
+ exit()
+}