From: fche Date: Tue, 6 Feb 2007 20:23:25 +0000 (+0000) Subject: * kernel_{string,long,...,char} protected accessor functions X-Git-Tag: release-0.5.13~84 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=f902d9596b3f7ee135d180ec0bae01c05d9a97bd;p=systemtap.git * kernel_{string,long,...,char} protected accessor functions * test suites for all of 'em too * even documentation * mm, donuts 2007-02-06 Frank Ch. Eigler * stapfuncs.5.in: Add docs for kernel_{long,int,short,char} and some user_string* variants. 2007-02-06 Frank Ch. Eigler * conversions.stp (kernel_long/int/short/char): New functions. 2007-02-06 Frank Ch. Eigler * buildok/conversions.stp: Build-test all conversions.stp functions. * systemtap.stress/conversions.*: New test. --- diff --git a/ChangeLog b/ChangeLog index 9227fa983..b62a81812 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2007-02-06 Frank Ch. Eigler + + * stapfuncs.5.in: Add docs for kernel_{long,int,short,char} and + some user_string* variants. + 2007-01-31 Martin Hunt * translate.cxx (translate_pass): Remove old string impedance diff --git a/stapfuncs.5.in b/stapfuncs.5.in index a76ff2406..af4cbd15d 100644 --- a/stapfuncs.5.in +++ b/stapfuncs.5.in @@ -65,15 +65,37 @@ unwind the current probe handler, nor block new probe handlers. 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 "" 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 "". .SS STRING .TP strlen:long (str:string) diff --git a/tapset/ChangeLog b/tapset/ChangeLog index 7131e4726..8e1766cd1 100644 --- a/tapset/ChangeLog +++ b/tapset/ChangeLog @@ -1,3 +1,7 @@ +2007-02-06 Frank Ch. Eigler + + * conversions.stp (kernel_long/int/short/char): New functions. + 2007-01-31 Martin Hunt * context.stp (print_backtrace): Modify for new diff --git a/tapset/conversions.stp b/tapset/conversions.stp index c311d25ac..fe5adc104 100644 --- a/tapset/conversions.stp +++ b/tapset/conversions.stp @@ -1,5 +1,5 @@ // 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 @@ -12,7 +12,8 @@ function kernel_string:string (addr:long) %{ /* pure */ 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; @@ -20,6 +21,59 @@ deref_fault: /* branched to from deref() */ 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 "" @@ -42,7 +96,7 @@ function user_string_warn:string (addr:long) %{ /* pure */ 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); @@ -54,5 +108,6 @@ function user_string_quoted:string (addr:long) %{ /* pure */ 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); %} diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index 2c72f3e54..fcae70c33 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-02-06 Frank Ch. Eigler + + * buildok/conversions.stp: Build-test all conversions.stp functions. + * systemtap.stress/conversions.*: New test. + 2007-01-29 Frank Ch. Eigler * systemtap.base/cache.exp (stap_compile): Accept new -p4 output. diff --git a/testsuite/buildok/conversions.stp b/testsuite/buildok/conversions.stp new file mode 100755 index 000000000..5a4d46f01 --- /dev/null +++ b/testsuite/buildok/conversions.stp @@ -0,0 +1,13 @@ +# 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 diff --git a/testsuite/systemtap.stress/conversions.exp b/testsuite/systemtap.stress/conversions.exp new file mode 100644 index 000000000..a7fd5e88f --- /dev/null +++ b/testsuite/systemtap.stress/conversions.exp @@ -0,0 +1,19 @@ + +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" +} diff --git a/testsuite/systemtap.stress/conversions.stp b/testsuite/systemtap.stress/conversions.stp new file mode 100644 index 000000000..797626ab1 --- /dev/null +++ b/testsuite/systemtap.stress/conversions.stp @@ -0,0 +1,15 @@ +#! stap +# Usage: set $1 to supply test address; -DMAXERRORS= + +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,"")) } +probe begin { print (user_string_warn ($1)) } +probe begin { print (user_string_quoted ($1)) } +probe begin(1) { print ("\n") exit () }