+2007-02-06 Frank Ch. Eigler <fche@elastic.org>
+
+ * stapfuncs.5.in: Add docs for kernel_{long,int,short,char} and
+ some user_string* variants.
+
2007-01-31 Martin Hunt <hunt@redhat.com>
* translate.cxx (translate_pass): Remove old string impedance
will shortly respond to the request and initiate an orderly shutdown.
.SS CONVERSIONS
+.PP
+These functions access kernel or user-space data. They try to validate the
+supplied addresses, and can thus result in errors if the pointers are invalid,
+or if a user-space access would cause a fault.
.TP
kernel_string:string (addr:long)
-Copy a string from kernel space at given address. The validation of this
-address is only partial at present.
+Copy a 0-terminated string from kernel space at given address.
+.TP
+kernel_long:long (addr:long)
+Copy a long from kernel space at given address.
+.TP
+kernel_int:long (addr:long)
+Copy an int from kernel space at given address.
+.TP
+kernel_short:long (addr:long)
+Copy a short from kernel space at given address.
+.TP
+kernel_char:long (addr:long)
+Copy a char from kernel space at given address.
.TP
user_string:string (addr:long)
-Copy a string from user space at given address. The validation of this
-address is only partial at present.
-
+Copy a string from user space at given address. If the access would
+fault, return "<unknown>" and signal no errors.
+.TP
+user_string2:string (addr:long, err_msg:string)
+Copy a string from user space at given address. If the access would
+fault, return instead the err_msg value.
+.TP
+user_string_warn:string (addr:long)
+Copy a string from user space at given address. If the access would
+fault, signal a warning and return "<unknown>".
.SS STRING
.TP
strlen:long (str:string)
+2007-02-06 Frank Ch. Eigler <fche@elastic.org>
+
+ * conversions.stp (kernel_long/int/short/char): New functions.
+
2007-01-31 Martin Hunt <hunt@redhat.com>
* context.stp (print_backtrace): Modify for new
// conversions tapset
-// Copyright (C) 2005, 2006 Red Hat Inc.
+// Copyright (C) 2005-2007 Red Hat Inc.
//
// This file is part of systemtap, and is free software. You can
// redistribute it and/or modify it under the terms of the GNU General
goto success;
deref_fault: /* branched to from deref() */
{
- static char errmsg[40];
+ /* XXX: concurrent errors could result in corrupted message string */
+ static char errmsg[50];
snprintf (errmsg, 40, "kernel string copy fault at 0x%p",
(void *) (uintptr_t) THIS->addr);
CONTEXT->last_error = errmsg;
success: ;
%}
+function kernel_long:long (addr:long) %{ /* pure */
+ THIS->__retvalue = (int64_t) deref (sizeof (long), (long *) (intptr_t) THIS->addr);
+ goto success;
+deref_fault: /* branched to from deref() */
+ {
+ static char errmsg[50];
+ snprintf (errmsg, 40, "kernel long copy fault at 0x%p",
+ (void *) (uintptr_t) THIS->addr);
+ CONTEXT->last_error = errmsg;
+ }
+success: ;
+%}
+
+function kernel_int:long (addr:long) %{ /* pure */
+ THIS->__retvalue = (int64_t) deref (sizeof (int), (int *) (intptr_t) THIS->addr);
+deref_fault: /* branched to from deref() */
+ {
+ static char errmsg[50];
+ snprintf (errmsg, 40, "kernel int copy fault at 0x%p",
+ (void *) (uintptr_t) THIS->addr);
+ CONTEXT->last_error = errmsg;
+ }
+success: ;
+%}
+
+function kernel_short:long (addr:long) %{ /* pure */
+ THIS->__retvalue = (int64_t) deref (sizeof (short), (short *) (intptr_t) THIS->addr);
+ goto success;
+deref_fault: /* branched to from deref() */
+ {
+ static char errmsg[50];
+ snprintf (errmsg, 40, "kernel short copy fault at 0x%p",
+ (void *) (uintptr_t) THIS->addr);
+ CONTEXT->last_error = errmsg;
+ }
+success: ;
+%}
+
+function kernel_char:long (addr:long) %{ /* pure */
+ THIS->__retvalue = (int64_t) deref (sizeof (char), (char *) (intptr_t) THIS->addr);
+ goto success;
+deref_fault: /* branched to from deref() */
+ {
+ static char errmsg[50];
+ snprintf (errmsg, 40, "kernel char copy fault at 0x%p",
+ (void *) (uintptr_t) THIS->addr);
+ CONTEXT->last_error = errmsg;
+ }
+success: ;
+%}
+
+
+
// On rare cases when userspace data is not accessible,
// this function returns "<unknown>"
long rc = _stp_strncpy_from_user (THIS->__retvalue,
(const char __user*) (uintptr_t) THIS->addr, MAXSTRINGLEN);
if (rc < 0) {
- static char errmsg[40];
+ static char errmsg[60];
snprintf (errmsg, 40, "user string copy fault %ld at %p", rc,
(void *) (uintptr_t) THIS->addr);
_stp_warn(errmsg);
if (THIS->addr == 0)
strlcpy (THIS->__retvalue, "NULL", MAXSTRINGLEN);
else
+ /* XXX: stp_text_str uses sleepy __get_user() => unsafe ?! */
_stp_text_str(THIS->__retvalue, (char *)(uintptr_t)THIS->addr, MAXSTRINGLEN, 1, 1);
%}
+2007-02-06 Frank Ch. Eigler <fche@elastic.org>
+
+ * buildok/conversions.stp: Build-test all conversions.stp functions.
+ * systemtap.stress/conversions.*: New test.
+
2007-01-29 Frank Ch. Eigler <fche@elastic.org>
* systemtap.base/cache.exp (stap_compile): Accept new -p4 output.
--- /dev/null
+# Test the conversions tapset.
+
+probe begin {
+ print (kernel_string(2342))
+ print (kernel_long(2342))
+ print (kernel_int(2342))
+ print (kernel_short(2342))
+ print (kernel_char(2342))
+
+ print (user_string(2342))
+ print (user_string2(2342,"foobar"))
+ print (user_string_warn(2342))
+}
\ No newline at end of file
--- /dev/null
+
+set file $srcdir/$subdir/conversions.stp
+foreach value {0 0xffffffff 0xffffffffffffffff} {
+ set test "conversions.stp $value"
+ if {![installtest_p]} { untested $test; continue }
+ spawn stap -DMAXERRORS=40 $file $value
+ set errs 0
+ verbose -log "exp $test $errs"
+ expect {
+ -re {ERROR[^\r\n]*\r\n} { incr errs; exp_continue }
+ -re {WARNING[^\r\n]*\r\n} { incr errs; exp_continue }
+ eof { }
+ timeout { }
+ }
+ verbose -log "done exp $test $errs"
+ wait
+ if {$errs == 8} { pass $test } else { fail "$test ($errs)" }
+ verbose -log "done $test $errs"
+}
--- /dev/null
+#! stap
+# Usage: set $1 to supply test address; -DMAXERRORS=<many>
+
+probe begin(-1) { print ("\n") }
+probe begin { print (kernel_string ($1)) }
+probe begin { print (kernel_long ($1)) }
+probe begin { print (kernel_int ($1)) }
+probe begin { print (kernel_short ($1)) }
+probe begin { print (kernel_char ($1)) }
+probe begin { print (kernel_int ($1)) }
+probe begin { print (user_string ($1)) }
+probe begin { print (user_string2 ($1,"<only suspected, not known>")) }
+probe begin { print (user_string_warn ($1)) }
+probe begin { print (user_string_quoted ($1)) }
+probe begin(1) { print ("\n") exit () }