1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
set test "unprivileged embedded C"
set arch [exec uname -i]
# normalize arch; PR4186
set arch [normalize_arch $arch]
# Some functions are only "native" for certain kernel versions.
set kv [exec uname -r | grep -o -G {^[0-9]\+.[0-9]\+.[0-9]\+}]
set kvbits [split $kv .]
set k1 [lindex $kvbits 0]
set k2 [lindex $kvbits 1]
set k3 [lindex $kvbits 2]
verbose -log "kernel version $k1.$k2.$k3"
# 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 { privilege test_fraction { transitive_test 0 } } {
global prototype_info test arch
global k1 k2 k3
set emsg2 "semantic error: embedded expression may not be used when --privilege=stapusr is specified"
# Test using --unprivileged and --privilege=stapusr. They should
# be equivalent.
set stapusr_options [list --unprivileged --privilege=stapusr ]
# Test using no option and --privilege=stapdev. They should be equivalent
set stapdev_options [list "" --privilege=stapdev ]
set test_num 0
set selector 0
foreach info $prototype_info {
set test_num [expr $test_num + 1]
verbose -log "testing $info"
# Select the proper --privilege option
switch $privilege {
stapusr {
set option [lindex $stapusr_options $selector]
}
stapdev {
set option [lindex $stapdev_options $selector]
}
default {
set option "--privilege=$privilege"
}
}
# Separate the prototype and its status.
set tokens [split $info ";"]
set prototype [lindex $tokens 0]
set status [lindex $tokens 1]
# Only test the specified fraction of the functions
if {[expr $test_num % $test_fraction] != 0} {
# untested "$test: $status: $option: $prototype"
continue
}
# Some function in earlier versions of systemtap were written
# in embedded-C, but later versions of systemtap had pure
# script versions. There is no point in testing these.
switch "$prototype" {
"probefunc ()"
{
untested "$test: $status: $option: $prototype (rewritten pure)"
continue
}
}
# Deprecated functions will be untested. The awk script that
# finds functions doesn't know about deprecated functions.
switch "$prototype" {
"cpuid ()" -
"get_mmap_args (long)"
{
untested "$test: $status: $option: $prototype (deprecated)"
continue
}
}
# Before 2.6.21 __get_skb_iphdr was pure script code. After
# 2.6.21, it is an embedded C function.
if { "$prototype" == "__get_skb_iphdr(long)" } {
if {($k1*256*256 + $k2*256 + $k3) < (2*256*256 + 6*256 + 21)} {
untested "$test: $status: $prototype"
continue
}
}
# If the function we're about to test doesn't contain any
# embedded C, we can't know if it calls any privileged
# functions. So, we won't bother testing functions without
# embedded C.
if { $status == "no embedded C" } {
untested "$test: $status: $prototype"
continue
}
# Test calling the function. If successful, the stap rc will be 0.
if { $transitive_test } {
set call [add_args $prototype]
set cmd [concat [list stap -p2 $option -e] "'function foo() { $call } probe begin { foo() }'"]
} else {
set call [add_args $prototype]
set cmd [concat [list stap -p2 $option -e] "'probe begin { $call }'"]
}
# XXX drop the pass2 standard output, ~800k lines in systemtap.log
# whereas standard error is kept for inspecting error messages
if {! [info exists env(SYSTEMTAP_SHOW_EMBEDDED_C)]} {
verbose -log "eval exec sh -c \"$cmd >/dev/null\""
set rc [catch {eval exec sh -c "\"$cmd >/dev/null\""} res_stap]
} else {
verbose -log "eval exec sh -c \"$cmd\""
set rc [catch {eval exec sh -c "\"$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"
set emsg1 "semantic error: function may not be used when --privilege=stapusr is specified: identifier '$funcname'"
set found [expr [regexp ".*$emsg1.*" $res_stap] || [regexp ".*$emsg2.*" $res_stap]]
# Evaluate the result based upon the function's status and the
# privilege level.
switch $status {
unprivileged -
myproc-unprivileged -
"no embedded C"
{
# There should be no message excluding this function
set passed [expr ! $found]
}
privileged
{
if {$privilege == "stapusr"} {
# There should be a message excluding this function
set passed $found
} else {
# There should be no message excluding this function
set passed [expr ! $found]
}
}
default
{
set passed 0
}
}
if {$passed} {
pass "$test: $status: $option: $prototype"
} else {
fail "$test: $status: $option: $prototype"
}
set selector [expr ($selector + 1) % 2]
}
}
# 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 "Looking for tapset scripts in $tapsetdir/linux"
set files [glob -nocomplain $tapsetdir/linux/*.stp]
verbose -log "Looking for tapset scripts in $tapsetdir/linux/[exec uname -i]"
set files [concat $files [glob -nocomplain $tapsetdir/linux/[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. We'll test all the embedded C functions.
test_embedded_C stapusr 1
test_embedded_C stapsys 1
#test_embedded_C stapdev 1
# Now let's make sure that privileged function are "transitive" -
# i.e. if an embedded-C function is privileged, then any pure script
# function that calls it is also privileged. Since we don't know the
# call graph information for functions, we'll define our own new pure
# script function that then calls the real embedded-C function. (See
# function "foo" above in test_embedded_C().)
#
# Here we'll just test a subset of the embedded C functions.
if {! [info exists env(SYSTEMTAP_TEST_ALL_EMBEDDED_C)]} {
# Test a subset (1/5) of the tapset functions containing embedded C code.
set test_fraction 5
} else {
# Test all of the tapset functions containing embedded C code.
set test_fraction 1
}
set test "$test (transitive)"
test_embedded_C stapusr $test_fraction 1
test_embedded_C stapsys $test_fraction 1
#test_embedded_C stapdev $test_fraction 1
|