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 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
|
set test "Server Argument Test"
if {! [nss_p]} { unsupported $test; return }
# Each test will take 3 seconds or more due to the use of avahi to browse for
# servers, so limit iterations to some small but reasonable number.
set iterations 10
# Allow seeding the random number generator using an environment variable in
# order to facilitate reproducing a given series of tests. Otherwise seed it
# using the current time.
if [info exists env(STAP_RANDOM_SEED)] {
set random_seed $env(STAP_RANDOM_SEED)
} else {
set random_seed [clock seconds]
}
verbose -log "Random seed is $random_seed"
expr srand($random_seed)
proc stap_direct_and_with_client {stap options} {
global installed_stap use_server
# tcl's 'eval' creates a string containing the arguments and
# recursively passes it to the tcl interpreter. Special
# characters need to be quoted.
regsub -all "\[\"\\\\;\]" $options {\\\0} options
regsub -all "\[\n\]" $options {\\n} options
# If the options contain -I/ or the equivalent, then the client will balk.
# So test that the client balks.
if {[regexp -- "\-I */$" $options] || [regexp -- "\-I */ " $options]} {
set passed 0
set fallthrough 0
set cmd [concat stap $options $use_server]
send_log "executing: $cmd\n"
eval spawn $cmd
expect {
-timeout 150
-re {^Unable to send / to the server\r\n} {
set passed 1
}
# Some other options can cause errors which occur before the one for -I/.
# If one of these errors occurs, then fall through to the normal test.
-re {^ERROR: Safety pattern mismatch for -. parameter .*\r\n} {
set fallthrough 1
}
-re {^.*\r\n} { exp_continue }
timeout {
kill -INT -[exp_pid] 2
}
}
catch {close}; catch {wait}
if { $fallthrough == 0 } {
return $passed
}
}
# Otherwise, check the that output from compiling directly and using
# the client/server are reasonable similar.
verbose -log "eval exec $stap $options"
catch {eval exec $stap $options} res_stap
verbose -log $res_stap
# Now run it using the client
verbose -log "eval exec $stap $use_server $options"
catch {eval exec $stap $use_server $options} res_stap_client
verbose -log $res_stap_client
# Now check the output
set skip_hostname_mode 0
set n 0
set expected [split $res_stap "\n"]
set received [split $res_stap_client "\n"]
foreach line $received {
# Instructed to skip hostnames?
if {$skip_hostname_mode} {
if {[regexp {^ \S+$} $line]} {
verbose -log "skipping: $line"
continue
} else {
set skip_hostname_mode 0
}
}
# Ignore warnings about the domain name on the certificate not matching
if {[regexp {^WARNING: The domain name, [^,]*, does not match the DNS name\(s\) on the server certificate:} $line]} {
set skip_hostname_mode 1
verbose -log "skipping: $line"
continue
}
set expected_line [lindex $expected $n]
# Some messages contain the names of files or directories
# and will be prefixed for the client.
if {[regexp "^ (.*)" $expected_line match data]} {
verbose -log "MATCH: $match"
verbose -log "DATA: $data"
# Special characters in the regexp need to be quoted.
regsub -all "\[\"\\\\;\*\(\)\]" $data {\\\0} data
if {[regexp "^ tapset.*/$data" $line]} {
incr n
continue
}
if {[regexp "^ runtime.*/$data" $line]} {
incr n
continue
}
# Some messages contain the name of the module based on the
# process id.
if {[regexp "^ stap_\[0-9\]*" $expected_line] &&
[regexp "^ stap_\[0-9\]*" $line]} {
incr n
continue
}
} elseif {[regexp "^Input file '(.*)' is empty or missing." $expected_line match data]} {
# Special characters in the regexp need to be quoted.
regsub -all "\[\"\\\\;\*\]" $data {\\\0} data
if {[regexp "^Input file 'script.*/$data' is empty or missing." $line]} {
incr n
continue
}
} elseif {[regexp "^Input file '(.*)' is missing." $expected_line match data]} {
# Special characters in the regexp need to be quoted.
regsub -all "\[\"\\\\;\*\]" $data {\\\0} data
if {[regexp "^Input file 'script.*/$data' is missing." $line]} {
incr n
continue
}
} elseif {[regexp "^(.*/stap): (.*)" $line match data1 data2]} {
# Special characters in the regexp need to be quoted.
regsub -all "\[\"\\\\;\*\]" $data2 {\\\0} data2
if {[regexp "^$stap: $data2" $expected_line]} {
incr n
continue
}
}
# Otherwise the output must be identical.
if {! [string equal $line $expected_line]} {
break
}
incr n
}
if {$n == [llength $expected] && [llength $expected] <= [llength $received]} {
# Test passes
return 1
}
# Test fails
send_log "line [expr $n + 1]:\n"
send_log "Expected: \"[lindex $expected $n]\"\n"
send_log "Got : \"$line\"\n"
return 0
}
# ************ Start of mainline *************
# Don't attempt these tests if the client/server are not available
if {! [setup_server]} then {
untested "$test"
return
}
# Make sure we call the correct instance of stap
# There is a copy of stap on the PATH which always uses --use-server NOT ANY MORE!!!
#if {[installtest_p]} then {
# # For 'make installcheck', use the installed stap
# set stap $installed_stap
#} else {
# # For 'make check' use stap from the build tree
# set stap [exec pwd]/../stap
#}
set stap stap
# Test some argument strings which have failed in the past. This is useful
# for debugging a currently failing case and helps to ensure that previously
# fixed cases do not regress.
# TODO: Debug this one: "-p1 -I -e\\;/ -Dhn6 -cejijqmi0 -S3-k -"
set previously_fixed [list \
"-p1 -I=\\w94\nbh -e -Dhfuo0iu7 -c" \
"-p1 -I8o\\2ie -e'1\\ -D\n\" -c" \
"-p1 -Ira\\3;c g -e0fle'qq -Dr/316k\\o8 -cjyoc\n3" \
"-p1 -I6p3 -elc -Dqgsgv' -c" \
"-p1 -I\"vyv;z -ej\"/3 -D/ 01qck\n -c3u55zut" \
"-p1 -I1 -eo9e\nx047q -D9xyefk0a -cvl98/x1'i" \
"-p1 -c; test.stp" \
"-p1 -I4hgy96 -e5oo39p -Ddx8v -c4;" \
"-p1 -I -esq3wors -Dz -c*eibz8h2e" \
"-p1 -I a -em339db5 -Du2;c0ps -ch9o\\" \
"-p1 -Ipfjps4 -ebug4dc -Du8vd fvkl -c" \
"-p1 -I0\"nspzjyf -e5r3up8h -Dmi;ojp9m -cx;a2fat" \
"-p1 -Iu -ek7;r -Dcu\"; -c\"hc" \
"-p1 -Icd4fidq m40mv -edn -D;8ha\\cjr -c1*vnq" \
"-p1 -I;3 -er8e -D -cb6k29z" \
"-p1 -Ircj -e -D -c\\vmww" \
"-p1 -Illc5 -e65wof9 qr*=x7x5 -D -cgx;" \
"-p1 -Iyaj420=3 -e\" -D -cd'5mi" \
"-p1 -Ir -e -D29\\ -cj2szt;4" \
"-p1 -Ibno3=b4sk -e' -Dg2-j;e -c2ijx'" \
"-p1 -I285v7pl -eo5\\0 -D86s -c-c*v" \
"-l syscall.open* -- -p5" \
"-l syscall.open* -- -rfoo" \
"-p1 -I/ 1\\nbzg3 -ebf -Do -ckrll=\\;oh -\S4" \
"-p1 -I / 1\\nbzg3 -ebf -Do -ckrll=\\;oh -\S4" \
"-p1 1\\nbzg3 -ebf -Do -ckrll=\\;oh -\S4 -I/" \
"-p1 1\\nbzg3 -ebf -Do -ckrll=\\;oh -\S4 -I /" \
"-p1 -I -e\\;/ -Dhn6 -cejijqmi0 -S3-k -" \
"-p1 -I/ -e/ -D -c\\n1v\\;nd8 -S--" \
"-p1 -I/ -e0xzu -Dxrk -c*sum8fe -St546jn" \
]
set i 0
foreach options $previously_fixed {
if {[stap_direct_and_with_client $stap $options]} {
pass "$test $i"
} else {
fail "$test $i"
}
incr i
}
# Generate semi-random arguments containing with potential problem characters.
# Check that running systemtap with the client/server generates output
# comparable to running stap directly.
set dangerous_options [list "-I" "-e" "-D" "-c" "-S"]
# NB: Other options could be candidates here, like -r and -B, but
# there stap-server imposes more restrictions than local stap, so
# this simple error-matching test cannot use them.
set argchars "0123456789/;*'=-\\\"\n abcdefghijklmnopqrstuvwxyz"
for {set i 0} {$i < $iterations} {incr i} {
verbose -log "Iteration $i"
# First generate an argument string
set options "-p1"
foreach option $dangerous_options {
set options "$options $option"
set limit [expr int(rand() * 10)]
for {set c 0} {$c < $limit} {incr c} {
set options "$options[string index $argchars [expr int(rand() * [string length $argchars])]]"
}
}
# Now test it against stap and stap client
if {[stap_direct_and_with_client $stap $options]} {
pass "Fuzzing $test $i"
} else {
fail "Fuzzing $test $i"
}
}
# Shudown the server.
shutdown_server
|