summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2010-02-05 14:53:06 -0500
committerDave Brolley <brolley@redhat.com>2010-02-05 14:53:06 -0500
commit3cad5a57f0117dcb994b72db454b3fa1805e5dd5 (patch)
treeda14b364bdc906188c9d580e9238f0faf7e33cb1
parentc33bb0d60c14eac88bdc50589799e1d065dec565 (diff)
parent08173df80b532dd000b32354bd0c765acaac4659 (diff)
downloadsystemtap-steved-3cad5a57f0117dcb994b72db454b3fa1805e5dd5.tar.gz
systemtap-steved-3cad5a57f0117dcb994b72db454b3fa1805e5dd5.tar.xz
systemtap-steved-3cad5a57f0117dcb994b72db454b3fa1805e5dd5.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
-rw-r--r--README.security30
-rw-r--r--aclocal.m422
-rwxr-xr-xconfigure146
-rw-r--r--configure.ac60
-rw-r--r--tapset/aux_syscalls.stp163
-rw-r--r--testsuite/systemtap.base/overflow-get_argv.exp5
-rw-r--r--testsuite/systemtap.base/overflow-get_argv.stp62
-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.stp609
13 files changed, 814 insertions, 353 deletions
diff --git a/README.security b/README.security
index 4f649d5d..b61139f4 100644
--- a/README.security
+++ b/README.security
@@ -88,26 +88,10 @@ program is a setuid program that does some system setup, loads the
kernel module, then runs stapio (and waits for it to finish). The
stapio program runs as the invoking user and is responsible for all
communication with the kernel module. After the script runs to
-completion, stapio exits and staprun unloads the kernel module.
-
-staprun is a setuid program that uses POSIX capabilities. Using POSIX
-capabilities allows the program to only have the privileges to do
-certain things. When staprun starts up, it only keeps the following
-POSIX capabilities and then switches its user-id/group-id to the
-invoking user:
-
- * CAP_SYS_MODULE - insert and remove kernel modules
- * CAP_SYS_ADMIN - misc, including mounting and unmounting
- * CAP_SYS_NICE - setpriority()
- * CAP_SETUID - allows setuid
- * CAP_SETGID - allows setgid
-
-The above capabilities are the permitted set of capabilities for
-staprun, which is the list of all the capabilities staprun is ever
-permitted to have. In addition, the effective set of capabilities, the
-capabilities from the permitted set that are currently enabled, is
-cleared. When needed, a particular capability is enabled, the
-operation is performed, then the capability is disabled. The staprun
-program was designed in this way to prevent several classes of security
-attacks. Security is also heightened by the fact that the only
-external program that staprun executes is stapio.
+completion, stapio fork/execs staprun -d to unload the kernel module.
+
+staprun is a setuid program. It holds on to the root priviliges only
+for the least amount of time (as required to verify/load compiled
+kernel module files). It invokes only stapio, and only as the
+original (unprivileged) user.
+
diff --git a/aclocal.m4 b/aclocal.m4
index 95a48395..382a870c 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -87,16 +87,14 @@ fi])
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
# ---------------------------------------------
m4_define([_PKG_CONFIG],
-[if test -n "$PKG_CONFIG"; then
- if test -n "$$1"; then
- pkg_cv_[]$1="$$1"
- else
- PKG_CHECK_EXISTS([$3],
- [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
- [pkg_failed=yes])
- fi
-else
- pkg_failed=untried
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
fi[]dnl
])# _PKG_CONFIG
@@ -140,9 +138,9 @@ See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
- $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
else
- $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
diff --git a/configure b/configure
index 6c904e2a..18651dab 100755
--- a/configure
+++ b/configure
@@ -6312,7 +6312,8 @@ else
enable_server="check"
fi
-# Extract the first word of "certutil", so it can be a program name with args.
+if test "$enable_server" != "no"; then
+ # Extract the first word of "certutil", so it can be a program name with args.
set dummy certutil; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
@@ -6350,7 +6351,7 @@ $as_echo "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nss3" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nss3" >&5
$as_echo_n "checking for /usr/include/nss3... " >&6; }
if test "${ac_cv_file__usr_include_nss3+set}" = set; then :
$as_echo_n "(cached) " >&6
@@ -6369,7 +6370,7 @@ if test "x$ac_cv_file__usr_include_nss3" = x""yes; then :
nssdir=nss3
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nss" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nss" >&5
$as_echo_n "checking for /usr/include/nss... " >&6; }
if test "${ac_cv_file__usr_include_nss+set}" = set; then :
$as_echo_n "(cached) " >&6
@@ -6391,7 +6392,7 @@ fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nspr4" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nspr4" >&5
$as_echo_n "checking for /usr/include/nspr4... " >&6; }
if test "${ac_cv_file__usr_include_nspr4+set}" = set; then :
$as_echo_n "(cached) " >&6
@@ -6410,7 +6411,7 @@ if test "x$ac_cv_file__usr_include_nspr4" = x""yes; then :
nsprdir=nspr4
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nspr" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /usr/include/nspr" >&5
$as_echo_n "checking for /usr/include/nspr... " >&6; }
if test "${ac_cv_file__usr_include_nspr+set}" = set; then :
$as_echo_n "(cached) " >&6
@@ -6432,15 +6433,15 @@ fi
fi
-if test "x$nssdir" != "x" -a "x$nsprdir" != "x"; then
-nss_CFLAGS="-I/usr/include/$nssdir"
-nspr_CFLAGS="-I/usr/include/$nsprdir"
+ if test "x$nssdir" != "x" -a "x$nsprdir" != "x"; then
+ nss_CFLAGS="-I/usr/include/$nssdir"
+ nspr_CFLAGS="-I/usr/include/$nsprdir"
-save_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CFLAGS $nss_CFLAGS $nspr_CFLAGS"
-have_nss_includes=yes
-for ac_header in "$nsprdir/nspr.h" "$nsprdir/plgetopt.h" "$nsprdir/prerror.h" "$nssdir/ssl.h" "$nssdir/nss.h" "$nssdir/pk11func.h" "$nssdir/secerr.h"
+ save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CFLAGS $nss_CFLAGS $nspr_CFLAGS"
+ have_nss_includes=yes
+ for ac_header in "$nsprdir/nspr.h" "$nsprdir/plgetopt.h" "$nsprdir/prerror.h" "$nssdir/ssl.h" "$nssdir/nss.h" "$nssdir/pk11func.h" "$nssdir/secerr.h"
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -6456,9 +6457,9 @@ fi
done
-CPPFLAGS="$save_CPPFLAGS"
-have_nss_libs=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PR_Connect in -lnspr4" >&5
+ CPPFLAGS="$save_CPPFLAGS"
+ have_nss_libs=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PR_Connect in -lnspr4" >&5
$as_echo_n "checking for PR_Connect in -lnspr4... " >&6; }
if test "${ac_cv_lib_nspr4_PR_Connect+set}" = set; then :
$as_echo_n "(cached) " >&6
@@ -6496,7 +6497,7 @@ fi
$as_echo "$ac_cv_lib_nspr4_PR_Connect" >&6; }
if test "x$ac_cv_lib_nspr4_PR_Connect" = x""yes; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_ReHandshake in -lssl3" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_ReHandshake in -lssl3" >&5
$as_echo_n "checking for SSL_ReHandshake in -lssl3... " >&6; }
if test "${ac_cv_lib_ssl3_SSL_ReHandshake+set}" = set; then :
$as_echo_n "(cached) " >&6
@@ -6539,19 +6540,20 @@ fi
fi
-fi
-if test "x${have_nss_includes}${have_nss_libs}${have_certutil}" != "xyesyesyes"; then
- if test "$enable_server" == "yes"; then
- as_fn_error "cannot find all libraries or tools for stap-server" "$LINENO" 5
fi
- if test "$enable_server" == "check"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: will not build stap-server, cannot find all libraries or tools" >&5
+ if test "x${have_nss_includes}${have_nss_libs}${have_certutil}" != "xyesyesyes"; then
+ if test "$enable_server" == "yes"; then
+ as_fn_error "cannot find all libraries or tools for stap-server" "$LINENO" 5
+ fi
+ if test "$enable_server" == "check"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: will not build stap-server, cannot find all libraries or tools" >&5
$as_echo "$as_me: WARNING: will not build stap-server, cannot find all libraries or tools" >&2;}
- fi
-else
+ fi
+ else
$as_echo "#define HAVE_NSS 1" >>confdefs.h
+ fi
fi
if test "x${have_nss_includes}${have_nss_libs}${have_certutil}" == "xyesyesyes" -a "$enable_server" != "no"; then
BUILD_SERVER_TRUE=
@@ -6834,11 +6836,10 @@ pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gtkmm" >&5
$as_echo_n "checking for gtkmm... " >&6; }
-if test -n "$PKG_CONFIG"; then
- if test -n "$gtkmm_CFLAGS"; then
- pkg_cv_gtkmm_CFLAGS="$gtkmm_CFLAGS"
- else
- if test -n "$PKG_CONFIG" && \
+if test -n "$gtkmm_CFLAGS"; then
+ pkg_cv_gtkmm_CFLAGS="$gtkmm_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtkmm-2.4 >= 2.8.0\""; } >&5
($PKG_CONFIG --exists --print-errors "gtkmm-2.4 >= 2.8.0") 2>&5
ac_status=$?
@@ -6848,15 +6849,13 @@ if test -n "$PKG_CONFIG"; then
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
-if test -n "$PKG_CONFIG"; then
- if test -n "$gtkmm_LIBS"; then
- pkg_cv_gtkmm_LIBS="$gtkmm_LIBS"
- else
- if test -n "$PKG_CONFIG" && \
+if test -n "$gtkmm_LIBS"; then
+ pkg_cv_gtkmm_LIBS="$gtkmm_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtkmm-2.4 >= 2.8.0\""; } >&5
($PKG_CONFIG --exists --print-errors "gtkmm-2.4 >= 2.8.0") 2>&5
ac_status=$?
@@ -6866,9 +6865,8 @@ if test -n "$PKG_CONFIG"; then
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
@@ -6881,9 +6879,9 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- gtkmm_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gtkmm-2.4 >= 2.8.0"`
+ gtkmm_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gtkmm-2.4 >= 2.8.0" 2>&1`
else
- gtkmm_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gtkmm-2.4 >= 2.8.0"`
+ gtkmm_PKG_ERRORS=`$PKG_CONFIG --print-errors "gtkmm-2.4 >= 2.8.0" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$gtkmm_PKG_ERRORS" >&5
@@ -6910,11 +6908,10 @@ pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libglade" >&5
$as_echo_n "checking for libglade... " >&6; }
-if test -n "$PKG_CONFIG"; then
- if test -n "$libglade_CFLAGS"; then
- pkg_cv_libglade_CFLAGS="$libglade_CFLAGS"
- else
- if test -n "$PKG_CONFIG" && \
+if test -n "$libglade_CFLAGS"; then
+ pkg_cv_libglade_CFLAGS="$libglade_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libglademm-2.4 >= 2.6.7\""; } >&5
($PKG_CONFIG --exists --print-errors "libglademm-2.4 >= 2.6.7") 2>&5
ac_status=$?
@@ -6924,15 +6921,13 @@ if test -n "$PKG_CONFIG"; then
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
-if test -n "$PKG_CONFIG"; then
- if test -n "$libglade_LIBS"; then
- pkg_cv_libglade_LIBS="$libglade_LIBS"
- else
- if test -n "$PKG_CONFIG" && \
+if test -n "$libglade_LIBS"; then
+ pkg_cv_libglade_LIBS="$libglade_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libglademm-2.4 >= 2.6.7\""; } >&5
($PKG_CONFIG --exists --print-errors "libglademm-2.4 >= 2.6.7") 2>&5
ac_status=$?
@@ -6942,9 +6937,8 @@ if test -n "$PKG_CONFIG"; then
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
@@ -6957,9 +6951,9 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- libglade_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "libglademm-2.4 >= 2.6.7"`
+ libglade_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libglademm-2.4 >= 2.6.7" 2>&1`
else
- libglade_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libglademm-2.4 >= 2.6.7"`
+ libglade_PKG_ERRORS=`$PKG_CONFIG --print-errors "libglademm-2.4 >= 2.6.7" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$libglade_PKG_ERRORS" >&5
@@ -7268,11 +7262,10 @@ pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for RPM" >&5
$as_echo_n "checking for RPM... " >&6; }
-if test -n "$PKG_CONFIG"; then
- if test -n "$RPM_CFLAGS"; then
- pkg_cv_RPM_CFLAGS="$RPM_CFLAGS"
- else
- if test -n "$PKG_CONFIG" && \
+if test -n "$RPM_CFLAGS"; then
+ pkg_cv_RPM_CFLAGS="$RPM_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rpm\""; } >&5
($PKG_CONFIG --exists --print-errors "rpm") 2>&5
ac_status=$?
@@ -7282,15 +7275,13 @@ if test -n "$PKG_CONFIG"; then
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
-if test -n "$PKG_CONFIG"; then
- if test -n "$RPM_LIBS"; then
- pkg_cv_RPM_LIBS="$RPM_LIBS"
- else
- if test -n "$PKG_CONFIG" && \
+if test -n "$RPM_LIBS"; then
+ pkg_cv_RPM_LIBS="$RPM_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"rpm\""; } >&5
($PKG_CONFIG --exists --print-errors "rpm") 2>&5
ac_status=$?
@@ -7300,9 +7291,8 @@ if test -n "$PKG_CONFIG"; then
else
pkg_failed=yes
fi
- fi
-else
- pkg_failed=untried
+ else
+ pkg_failed=untried
fi
@@ -7315,9 +7305,9 @@ else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
- RPM_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "rpm"`
+ RPM_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "rpm" 2>&1`
else
- RPM_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "rpm"`
+ RPM_PKG_ERRORS=`$PKG_CONFIG --print-errors "rpm" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$RPM_PKG_ERRORS" >&5
diff --git a/configure.ac b/configure.ac
index 2ec625d3..8a828de9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -287,38 +287,40 @@ AC_ARG_ENABLE([server],
[enable building of stap-server/client (default on if nss etc. found).]),
[enable_server=$enableval],
[enable_server="check"])
+if test "$enable_server" != "no"; then
dnl Find the location of nss and nspr headers and certutil
-AC_CHECK_PROG(have_certutil, certutil, [yes], [no])
-AC_CHECK_FILE([/usr/include/nss3], nssdir=nss3, [
- AC_CHECK_FILE([/usr/include/nss], nssdir=nss)
-])
-AC_CHECK_FILE([/usr/include/nspr4], nsprdir=nspr4, [
- AC_CHECK_FILE([/usr/include/nspr], nsprdir=nspr)
-])
-if test "x$nssdir" != "x" -a "x$nsprdir" != "x"; then
-nss_CFLAGS="-I/usr/include/$nssdir"
-nspr_CFLAGS="-I/usr/include/$nsprdir"
-AC_SUBST(nss_CFLAGS)
-AC_SUBST(nspr_CFLAGS)
-save_CPPFLAGS="$CPPFLAGS"
-CPPFLAGS="$CFLAGS $nss_CFLAGS $nspr_CFLAGS"
-have_nss_includes=yes
-AC_CHECK_HEADERS(["$nsprdir/nspr.h" "$nsprdir/plgetopt.h" "$nsprdir/prerror.h" "$nssdir/ssl.h" "$nssdir/nss.h" "$nssdir/pk11func.h" "$nssdir/secerr.h"], [], have_nss_includes=no)
-CPPFLAGS="$save_CPPFLAGS"
-have_nss_libs=no
-AC_CHECK_LIB(nspr4, PR_Connect, [
- AC_CHECK_LIB(ssl3, SSL_ReHandshake, have_nss_libs=yes)
-])
-fi
-if test "x${have_nss_includes}${have_nss_libs}${have_certutil}" != "xyesyesyes"; then
- if test "$enable_server" == "yes"; then
- AC_MSG_ERROR([cannot find all libraries or tools for stap-server])
+ AC_CHECK_PROG(have_certutil, certutil, [yes], [no])
+ AC_CHECK_FILE([/usr/include/nss3], nssdir=nss3, [
+ AC_CHECK_FILE([/usr/include/nss], nssdir=nss)
+ ])
+ AC_CHECK_FILE([/usr/include/nspr4], nsprdir=nspr4, [
+ AC_CHECK_FILE([/usr/include/nspr], nsprdir=nspr)
+ ])
+ if test "x$nssdir" != "x" -a "x$nsprdir" != "x"; then
+ nss_CFLAGS="-I/usr/include/$nssdir"
+ nspr_CFLAGS="-I/usr/include/$nsprdir"
+ AC_SUBST(nss_CFLAGS)
+ AC_SUBST(nspr_CFLAGS)
+ save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CFLAGS $nss_CFLAGS $nspr_CFLAGS"
+ have_nss_includes=yes
+ AC_CHECK_HEADERS(["$nsprdir/nspr.h" "$nsprdir/plgetopt.h" "$nsprdir/prerror.h" "$nssdir/ssl.h" "$nssdir/nss.h" "$nssdir/pk11func.h" "$nssdir/secerr.h"], [], have_nss_includes=no)
+ CPPFLAGS="$save_CPPFLAGS"
+ have_nss_libs=no
+ AC_CHECK_LIB(nspr4, PR_Connect, [
+ AC_CHECK_LIB(ssl3, SSL_ReHandshake, have_nss_libs=yes)
+ ])
fi
- if test "$enable_server" == "check"; then
- AC_MSG_WARN([will not build stap-server, cannot find all libraries or tools])
+ if test "x${have_nss_includes}${have_nss_libs}${have_certutil}" != "xyesyesyes"; then
+ if test "$enable_server" == "yes"; then
+ AC_MSG_ERROR([cannot find all libraries or tools for stap-server])
+ fi
+ if test "$enable_server" == "check"; then
+ AC_MSG_WARN([will not build stap-server, cannot find all libraries or tools])
+ fi
+ else
+ AC_DEFINE([HAVE_NSS], [1], [Define to 1 if you have the nss libraries.])
fi
-else
- AC_DEFINE([HAVE_NSS], [1], [Define to 1 if you have the nss libraries.])
fi
AM_CONDITIONAL([BUILD_SERVER], [test "x${have_nss_includes}${have_nss_libs}${have_certutil}" == "xyesyesyes" -a "$enable_server" != "no"])
AM_CONDITIONAL([HAVE_NSS], [test "x${have_nss_includes}${have_nss_libs}${have_certutil}" == "xyesyesyes"])
diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp
index 2d0ba210..e762b37a 100644
--- a/tapset/aux_syscalls.stp
+++ b/tapset/aux_syscalls.stp
@@ -399,128 +399,53 @@ function __sem_flags:string(semflg:long)
/* This function copies an argv from userspace. */
-function __get_argv:string(a:long, first:long)
-%{ /* pure */
- char __user *__user *argv = (char __user *__user *)(long)THIS->a;
- char __user *vstr;
- int space, rc, len = MAXSTRINGLEN;
- char *str = THIS->__retvalue;
- char buf[80];
- char *ptr = buf;
-
-
- if (THIS->first && argv)
- argv++;
-
- while (argv != NULL && len) {
- if (__stp_get_user (vstr, argv))
- break;
-
- if (vstr == NULL)
- break;
-
- rc = _stp_strncpy_from_user(buf, vstr, 79);
- if (rc <= 0)
- break;
-
- /* check for whitespace in string */
- buf[rc] = 0;
- ptr = buf;
- space = 0;
- while (*ptr && rc--) {
- if (isspace(*ptr++)) {
- space = 1;
- break;
- }
- }
-
- if (len != MAXSTRINGLEN && len) {
- *str++=' ';
- len--;
- }
-
- if (space && len) {
- *str++='\"';
- len--;
- }
-
- rc = min(len, (int) strlcpy (str, buf, len));
- str += rc;
- len -= rc;
-
- if (space && len) {
- *str++='\"';
- len--;
- }
-
- argv++;
+function __get_argv:string(argv:long, first:long)
+{
+%( CONFIG_64BIT == "y" %?
+ if (first && argv)
+ argv += 8
+ while (argv) {
+ vstr = user_long(argv)
+ if (!vstr)
+ break
+ if (len)
+ str .= " "
+ str .= user_string_quoted(vstr)
+
+ newlen = strlen(str)
+ if (newlen == len)
+ break
+ len = newlen
+ argv += 8
}
- if (!len)
- --str;
- *str = 0;
-%}
-/* This function copies an argv from userspace. */
-function __get_compat_argv:string(a:long, first:long)
-%{ /* pure */
-#ifdef CONFIG_COMPAT
- compat_uptr_t __user *__user *argv = (compat_uptr_t __user *__user *)(long)THIS->a;
- compat_uptr_t __user *vstr;
- int space, rc, len = MAXSTRINGLEN;
- char *str = THIS->__retvalue;
- char buf[80];
- char *ptr = buf;
-
- if (THIS->first && argv)
- argv++;
-
- while (argv != NULL && len) {
- if (__stp_get_user (vstr, argv))
- break;
-
- if (vstr == NULL)
- break;
-
- rc = _stp_strncpy_from_user(buf, (char *)vstr, 79);
- if (rc <= 0)
- break;
-
- /* check for whitespace in string */
- buf[rc] = 0;
- ptr = buf;
- space = 0;
- while (*ptr && rc--) {
- if (isspace(*ptr++)) {
- space = 1;
- break;
- }
- }
- if (len != MAXSTRINGLEN && len) {
- *str++=' ';
- len--;
- }
-
- if (space && len) {
- *str++='\"';
- len--;
- }
-
- rc = min(len, (int) strlcpy (str, buf, len));
- str += rc;
- len -= rc;
-
- if (space && len) {
- *str++='\"';
- len--;
- }
-
- argv++;
+ return str
+%:
+ return __get_compat_argv(argv, first)
+%)
+}
+/* This function copies an argv from userspace. */
+function __get_compat_argv:string(argv:long, first:long)
+{
+ if (first && argv)
+ argv += 4
+ while (argv) {
+ vstr = user_int(argv) & 0xffffffff
+ if (!vstr)
+ break
+ if (len)
+ str .= " "
+ str .= user_string_quoted(vstr)
+
+ newlen = strlen(str)
+ if (newlen == len)
+ break
+ len = newlen
+ argv += 4
}
- if (!len)
- --str;
- *str = 0;
-#endif
-%}
+
+ return str
+}
/*
* Return the symbolic string representation
diff --git a/testsuite/systemtap.base/overflow-get_argv.exp b/testsuite/systemtap.base/overflow-get_argv.exp
deleted file mode 100644
index ac7fddc5..00000000
--- a/testsuite/systemtap.base/overflow-get_argv.exp
+++ /dev/null
@@ -1,5 +0,0 @@
-# PR11234: __get_argv can overflow its return buffer
-
-set test "overflow-get_argv"
-
-stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g -c "/bin/true /usr/bin/*"
diff --git a/testsuite/systemtap.base/overflow-get_argv.stp b/testsuite/systemtap.base/overflow-get_argv.stp
deleted file mode 100644
index 159ef4a8..00000000
--- a/testsuite/systemtap.base/overflow-get_argv.stp
+++ /dev/null
@@ -1,62 +0,0 @@
-// PR11234: __get_argv can overflow its return buffer
-
-// __get_argv has a signature like this:
-// struct function___get_argv_locals {
-// int64_t a;
-// int64_t first;
-// string_t __retvalue;
-// } function___get_argv;
-//
-// These functions are meant to have an overlap such that we can tell if
-// __get_argv overran its __retvalue.
-//
-// int64_t x;
-// int64_t y;
-// string_t z;
-// string_t __retvalue;
-//
-// NB: __retvalue[0] always gets cleared on call, but the rest should be
-// untouched, so we can use it as a sentinal.
-
-function clear:string(x:long, y:long, z:string) %{
- memset(THIS->__retvalue, 0, MAXSTRINGLEN);
-%}
-
-function check:string(x:long, y:long, z:string) %{
- int i, bad = 0;
- for (i=1; i<MAXSTRINGLEN; ++i)
- if (THIS->__retvalue[i])
- ++bad;
-
- if (bad)
- snprintf(THIS->__retvalue, MAXSTRINGLEN, "%d non-zero bytes", bad);
- else
- strlcpy(THIS->__retvalue, "ok", MAXSTRINGLEN);
-%}
-
-global result = "untested"
-
-probe syscall.execve {
- if (pid() != target())
- next
-
- clear(0, 0, "")
- foo = __get_argv($argv, 0)
- result = check(0, 0, "")
-
- // ensure that foo isn't optimized away
- if (foo == "foo")
- next
-}
-
-probe begin {
- println("systemtap starting probe")
-}
-
-probe end {
- println("systemtap ending probe")
- if (result == "ok")
- println("systemtap test success")
- else
- println("systemtap test failure: ", result)
-}
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..3b968625
--- /dev/null
+++ b/testsuite/systemtap.examples/process/pfiles.stp
@@ -0,0 +1,609 @@
+#! /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>
+#include <linux/tcp.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 optfam;
+ int optnum;
+ const char *optname;
+ int show_val;
+ } *p;
+ struct optname_item optname_entries[] = {
+ { SOL_SOCKET, SO_DEBUG, "SO_DEBUG", 0 },
+ { SOL_SOCKET, SO_REUSEADDR, "SO_REUSEADDR", 0 },
+ { SOL_SOCKET, SO_DONTROUTE, "SO_DONTROUTE", 0 },
+ { SOL_SOCKET, SO_BROADCAST, "SO_BROADCAST", 0 },
+ { SOL_SOCKET, SO_KEEPALIVE, "SO_KEEPALIVE", 0 },
+ { SOL_SOCKET, SO_OOBINLINE, "SO_OOBINLINE", 0 },
+ { SOL_SOCKET, SO_PASSCRED, "SO_PASSCRED", 0 },
+/* { SOL_SOCKET, SO_SNDLOWAT, "SO_SNDLOWAT", 0 },*/
+ { SOL_SOCKET, SO_TYPE, "SO_TYPE", 1 },
+ { SOL_SOCKET, SO_ERROR, "SO_ERROR", 1 },
+ { SOL_SOCKET, SO_SNDBUF, "SO_SNDBUF", 1 },
+ { SOL_SOCKET, SO_RCVBUF, "SO_RCVBUF", 1 },
+ { SOL_SOCKET, SO_NO_CHECK, "SO_NO_CHECK", 1 },
+ { SOL_TCP, TCP_NODELAY, "TCP_NODELAY", 0 },
+ { 0, 0, NULL, 0 },
+ };
+
+ for (p = optname_entries; p->optname; ++p) {
+ optlen = sizeof(optval);
+ ret = kernel_getsockopt(sock, p->optfam, 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()
+}