File: unprivileged_embedded_C.exp

package info (click to toggle)
systemtap 5.1-5
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 47,964 kB
  • sloc: cpp: 80,838; ansic: 54,757; xml: 49,725; exp: 43,665; sh: 11,527; python: 5,003; perl: 2,252; tcl: 1,312; makefile: 1,006; javascript: 149; lisp: 105; awk: 101; asm: 91; java: 70; sed: 16
file content (221 lines) | stat: -rw-r--r-- 7,257 bytes parent folder | download | duplicates (3)
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