From d40cad18f4616601520b53661fa2c100083a9265 Mon Sep 17 00:00:00 2001 From: Dave Brolley Date: Tue, 6 Sep 2011 15:48:29 -0400 Subject: [PATCH] PR11441 - unprivileged mode test suite enhancements. - Created a script which identifies all embedded C code in our tapset sources. - Tests to ensure that calls to each function containing embedded C are accepted/rejected for unprivileged users, as appropriate. --- .../systemtap.unprivileged/embeddedc.awk | 145 ++++++++++++++++++ .../unprivileged_embedded_C.exp | 99 ++++++++++++ ...ileged_all.exp => unprivileged_probes.exp} | 0 3 files changed, 244 insertions(+) create mode 100755 testsuite/systemtap.unprivileged/embeddedc.awk create mode 100644 testsuite/systemtap.unprivileged/unprivileged_embedded_C.exp rename testsuite/systemtap.unprivileged/{unprivileged_all.exp => unprivileged_probes.exp} (100%) diff --git a/testsuite/systemtap.unprivileged/embeddedc.awk b/testsuite/systemtap.unprivileged/embeddedc.awk new file mode 100755 index 000000000..cb2a5d20e --- /dev/null +++ b/testsuite/systemtap.unprivileged/embeddedc.awk @@ -0,0 +1,145 @@ +#!/bin/awk -f + +BEGIN { + isfunc = 0 + block = 0 + embedded = 0 +} + +# print the function prototype, all on one line. +/^function/ { + if (block != 0 || embedded != 0) { + printf "Unterminated block at: %s: %d %d\n",$0,block,embedded > "/dev/stderr" + exit 1 + } + isfunc = 1 + unprivileged = -1 + myproc_unprivileged = -1 +} + +/^function/,/\)/ { + # Strip characters after the ')'. + temp = $0 + sub("\\).*", ")", temp) +# print "after stripping trailing chars: " temp + + # Strip the the return type. + temp = gensub("^function[[:space:]]*([\\$_[:alpha:]][\\$_[:alnum:]]*)[[:space:]]*:[[:space:]]*[[:alpha:]]*", + "function \\1", 1, temp) +# print "after stripping return type: " temp + + # Strip the 'function'. + temp = gensub("^function[[:space:]]*", "", 1, temp) +# print "after stripping function: " temp + + # Add the default type where it has been omitted. + do { + temp1 = temp + temp = gensub("([(,][[:space:]]*[\\$_[:alpha:]][\\$_[:alnum:]]*)[[:space:]]*([,)])", + "\\1:long\\2", "g", temp) +# print "after adding a default type: " temp + } while (temp != temp1) + + # Strip paramater names. + temp = gensub("[\\$_[:alpha:]][\\$_[:alnum:]]*[[:space:]]*:[[:space:]]*([[:alpha:]])", + "\\1", "g", temp) +# print "after stripping parm names: " + + printf "%s",temp + fflush() +} + +# Beginning of an embedded C block +(! /^.*\/\/.*%{/) && /%{/ { + block += 1 + embedded += 1 +# printf "%s",$0 +# print ": embedded start:" block " " embedded +} + +# Beginning of a preprocessor block +(! /^.*\/\/.*%\(/) && /%\(/ { + block += 1 +# printf "%s",$0 +# print ": preprocessor start:" block " " embedded +} + +# Beginning of a code block +/^{/ { + block += 1 +# printf "%s",$0 +# print ": block start:" block " " embedded +} +(! /^.*\/\/.*{/) && /[^%]{/ { + block += 1 +# printf "%s",$0 +# print ": block start:" block " " embedded +} + +# unprivileged? +/\/\* unprivileged \*\// { + if (embedded && unprivileged != 0) + unprivileged = 1 +} +/\/\* myproc-unprivileged \*\// { + if (embedded && myproc_unprivileged != 0) + myproc_unprivileged = 1 +} + +# Process the end of a tapset function. +function finish_function() { + if (block == 0 && isfunc) { + if (unprivileged == 1) + print " ; unprivileged" + else if (myproc_unprivileged == 1) + print " ;myproc-unprivileged" + else if (unprivileged != -1 || myproc_unprivileged != -1) + print " ;privileged" + else + print " ;no embedded C" + fflush() + isfunc = 0 + } +} + +# End of an embedded C block +(! /^.*\/\/.*%}/) && /%}/ { + embedded -= 1 + block -= 1 + if (unprivileged == -1) + unprivileged = 0 + if (myproc_unprivileged == -1) + myproc_unprivileged = 0 +# printf "%s",$0 +# print ": embedded end:" block " " embedded + finish_function() +} + +# End of a preprocessor C block +(! /^.*\/\/.*%\)/) && /%\)/ { + block -= 1 +# printf "%s",$0 +# print ": embedded end:" block " " embedded + finish_function() +} + +# End of a code block +/^}/ { + block -= 1 +# printf "%s",$0 +# print ": block end:" block " " embedded + finish_function() +} +(! /^.*\/\/.*}/) && /[^%]}/ { + block -= 1 +# printf "%s",$0 +# print ": block end:" block " " embedded + finish_function() +} + +END { + if (block != 0 || embedded != 0) { + printf "Unterminated block at EOF: %d %d\n",block,embedded > "/dev/stderr" + exit 1 + } +} \ No newline at end of file diff --git a/testsuite/systemtap.unprivileged/unprivileged_embedded_C.exp b/testsuite/systemtap.unprivileged/unprivileged_embedded_C.exp new file mode 100644 index 000000000..5d1440a5e --- /dev/null +++ b/testsuite/systemtap.unprivileged/unprivileged_embedded_C.exp @@ -0,0 +1,99 @@ +set test "unprivileged embedded C" + +# Add arguments to a probe type template. +proc add_args { prototype } { + set call "$prototype" + + # Replace long with 0 + regsub -all "(\[(,]\[\[:space:]]*)long" $call "\\10" call + + # Replace string with "0" + regsub -all "(\[(,]\[\[:space:]]*)string" $call "\\1\"0\"" call + + return "$call" +} + +# Test valid probe types +proc test_embedded_C { use_wrapper } { + global prototype_info test + + if { $use_wrapper } { + set with_wrapper " with wrapper" + } else { + set with_wrapper "" + } + + foreach info $prototype_info { + verbose -log "testing $info" + + # Separate the prototype and its status. + set tokens [split $info ";"] + set prototype [lindex $tokens 0] + set status [lindex $tokens 1] + + # Test calling the function. If successful, the stap rc will be 0. + set call [add_args $prototype] + set cmd [concat [list stap -p2 --unprivileged -e "probe begin { $call }"]] + verbose -log "eval exec $cmd" + set rc [catch {eval exec $cmd} res_stap] + verbose -log $res_stap + + # Look for a message saying that the function is not allowed for unprivileged users. + regexp "(\[^\[:space:](]*).*" $prototype match funcname + verbose -log "funcname is $funcname" + + # The function '_wait_status_str' is not allowed for unprivileged but it fails with a + # reference to the function '_signal_name' which it calls and which is checked first. + if {"$funcname" == "_wait_status_str"} { + set funcname "_signal_name" + } + set emsg1 "semantic error: function may not be used when --unprivileged is specified: identifier '$funcname'" + set emsg2 "semantic error: embedded expression may not be used when --unprivileged is specified" + set found [expr [regexp ".*$emsg1.*" $res_stap] || [regexp ".*$emsg2.*" $res_stap]] + + # Evaluate the result based upon the function's status + switch $status { + unprivileged - + myproc-unprivileged - + "no embedded C" + { + # There should be no message excluding this function + set passed [expr ! $found] + } + privileged + { + # There should be a message excluding this function + set passed $found + } + } + + if {$passed} { + pass "$test: $status: $prototype" + } else { + fail "$test: $status: $prototype" + } + } +} + +# Obtain the prototypes of all tapset functions containing embedded C code. +set tapsetdir "$srcdir/../tapset" +verbose -log "Looking for tapset scripts in $tapsetdir" +set files [glob -nocomplain $tapsetdir/*.stp] +verbose -log "Looking for tapset scripts in $tapsetdir/[exec uname -i]" +set files [concat $files [glob -nocomplain $tapsetdir/[exec uname -i]/*.stp]] + +verbose -log "eval exec $srcdir/$subdir/embeddedc.awk [join $files]" +catch {eval exec $srcdir/$subdir/embeddedc.awk [join $files]} res_stap +set prototype_info [split $res_stap "\n"] + +verbose -log "prototype_info contains [llength prototype_info] items" +if {[llength prototype_info] > 0} { + pass "$test: Obtain list tapset functions containing embedded C" +} else { + fail "$test: Obtain list tapset functions containing embedded C" + untested "$test" + return +} + +# Now run the tests +test_embedded_C 0 diff --git a/testsuite/systemtap.unprivileged/unprivileged_all.exp b/testsuite/systemtap.unprivileged/unprivileged_probes.exp similarity index 100% rename from testsuite/systemtap.unprivileged/unprivileged_all.exp rename to testsuite/systemtap.unprivileged/unprivileged_probes.exp -- 2.43.5