summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Smith <dsmith@redhat.com>2010-01-26 13:40:51 -0600
committerDavid Smith <dsmith@redhat.com>2010-01-26 13:40:51 -0600
commit6390a48a6dfb88c9692af877e1767ce6cc8030d0 (patch)
tree3eee6e605f49701ace44f5c130db8b2cedcb6d3f
parent9f49a9853caff67bcc5de7dfe2c52ab1ae7f3738 (diff)
downloadsystemtap-steved-6390a48a6dfb88c9692af877e1767ce6cc8030d0.tar.gz
systemtap-steved-6390a48a6dfb88c9692af877e1767ce6cc8030d0.tar.xz
systemtap-steved-6390a48a6dfb88c9692af877e1767ce6cc8030d0.zip
Fixed PR 11223 by null terminating strings in procfs write probes.
* tapset-procfs.cxx (procfs_var_expanding_visitor::visit_target_symbol): Correctly null terminate strings in procfs write probes. * testsuite/systemtap.base/procfs_write.exp: New test.
-rw-r--r--tapset-procfs.cxx7
-rw-r--r--testsuite/systemtap.base/procfs_write.exp135
2 files changed, 139 insertions, 3 deletions
diff --git a/tapset-procfs.cxx b/tapset-procfs.cxx
index aa75af42..f5ab95f8 100644
--- a/tapset-procfs.cxx
+++ b/tapset-procfs.cxx
@@ -383,9 +383,10 @@ procfs_var_expanding_visitor::visit_target_symbol (target_symbol* e)
string locvalue = "CONTEXT->data";
if (! lvalue)
- ec->code = string("_stp_copy_from_user(THIS->__retvalue, ((struct _stp_procfs_data *)(")
- + locvalue + string("))->buffer, ((struct _stp_procfs_data *)(") + locvalue
- + string("))->count); /* pure */");
+ ec->code = string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string("); /* pure */\n")
+
+ + string(" _stp_copy_from_user(THIS->__retvalue, data->buffer, data->count);\n")
+ + string(" THIS->__retvalue[data->count] = '\\0';\n");
else
ec->code = string("int bytes = 0;\n")
+ string(" struct _stp_procfs_data *data = (struct _stp_procfs_data *)(") + locvalue + string(");\n")
diff --git a/testsuite/systemtap.base/procfs_write.exp b/testsuite/systemtap.base/procfs_write.exp
new file mode 100644
index 00000000..5bb35532
--- /dev/null
+++ b/testsuite/systemtap.base/procfs_write.exp
@@ -0,0 +1,135 @@
+# PR 11223. Make sure we can handle large amounts of procfs write data.
+
+set test "PROCFS_WRITE"
+
+if {![installtest_p]} { untested $test; return }
+
+proc proc_write_value { test path value} {
+ if [catch {open $path WRONLY} channel] {
+ fail "$test $channel"
+ } else {
+ puts $channel $value
+ close $channel
+ pass "$test wrote $value"
+ }
+}
+
+# This test string is ~4224 bytes long (66 lines of 64 chars). The
+# procfs kernel system will use a buffer of 4K. Our string of ~4224
+# should take around 9 trips through the write function (4224 chars /
+# 512 bytes per systemtap string = ~9 trips).
+#
+# The kernel reuses the 4K buffer for the 9th trip and doesn't null
+# terminate the string. Instead, it tells consumers how many bytes
+# are present.
+#
+# We want to make sure we can handle > 4K worth of data properly.
+set test_string \
+" 0:12345678901234567890123456789012345678901234567890123456789
+ 1:12345678901234567890123456789012345678901234567890123456789
+ 2:12345678901234567890123456789012345678901234567890123456789
+ 3:12345678901234567890123456789012345678901234567890123456789
+ 4:12345678901234567890123456789012345678901234567890123456789
+ 5:12345678901234567890123456789012345678901234567890123456789
+ 6:12345678901234567890123456789012345678901234567890123456789
+ 7:12345678901234567890123456789012345678901234567890123456789
+ 8:12345678901234567890123456789012345678901234567890123456789
+ 9:12345678901234567890123456789012345678901234567890123456789
+ 10:12345678901234567890123456789012345678901234567890123456789
+ 11:12345678901234567890123456789012345678901234567890123456789
+ 12:12345678901234567890123456789012345678901234567890123456789
+ 13:12345678901234567890123456789012345678901234567890123456789
+ 14:12345678901234567890123456789012345678901234567890123456789
+ 15:12345678901234567890123456789012345678901234567890123456789
+ 16:12345678901234567890123456789012345678901234567890123456789
+ 17:12345678901234567890123456789012345678901234567890123456789
+ 18:12345678901234567890123456789012345678901234567890123456789
+ 19:12345678901234567890123456789012345678901234567890123456789
+ 20:12345678901234567890123456789012345678901234567890123456789
+ 21:12345678901234567890123456789012345678901234567890123456789
+ 22:12345678901234567890123456789012345678901234567890123456789
+ 23:12345678901234567890123456789012345678901234567890123456789
+ 24:12345678901234567890123456789012345678901234567890123456789
+ 25:12345678901234567890123456789012345678901234567890123456789
+ 26:12345678901234567890123456789012345678901234567890123456789
+ 27:12345678901234567890123456789012345678901234567890123456789
+ 28:12345678901234567890123456789012345678901234567890123456789
+ 29:12345678901234567890123456789012345678901234567890123456789
+ 30:12345678901234567890123456789012345678901234567890123456789
+ 31:12345678901234567890123456789012345678901234567890123456789
+ 32:12345678901234567890123456789012345678901234567890123456789
+ 33:12345678901234567890123456789012345678901234567890123456789
+ 34:12345678901234567890123456789012345678901234567890123456789
+ 35:12345678901234567890123456789012345678901234567890123456789
+ 36:12345678901234567890123456789012345678901234567890123456789
+ 37:12345678901234567890123456789012345678901234567890123456789
+ 38:12345678901234567890123456789012345678901234567890123456789
+ 39:12345678901234567890123456789012345678901234567890123456789
+ 40:12345678901234567890123456789012345678901234567890123456789
+ 41:12345678901234567890123456789012345678901234567890123456789
+ 42:12345678901234567890123456789012345678901234567890123456789
+ 43:12345678901234567890123456789012345678901234567890123456789
+ 44:12345678901234567890123456789012345678901234567890123456789
+ 45:12345678901234567890123456789012345678901234567890123456789
+ 46:12345678901234567890123456789012345678901234567890123456789
+ 47:12345678901234567890123456789012345678901234567890123456789
+ 48:12345678901234567890123456789012345678901234567890123456789
+ 49:12345678901234567890123456789012345678901234567890123456789
+ 50:12345678901234567890123456789012345678901234567890123456789
+ 51:12345678901234567890123456789012345678901234567890123456789
+ 52:12345678901234567890123456789012345678901234567890123456789
+ 53:12345678901234567890123456789012345678901234567890123456789
+ 54:12345678901234567890123456789012345678901234567890123456789
+ 55:12345678901234567890123456789012345678901234567890123456789
+ 56:12345678901234567890123456789012345678901234567890123456789
+ 57:12345678901234567890123456789012345678901234567890123456789
+ 58:12345678901234567890123456789012345678901234567890123456789
+ 59:12345678901234567890123456789012345678901234567890123456789
+ 60:12345678901234567890123456789012345678901234567890123456789
+ 61:12345678901234567890123456789012345678901234567890123456789
+ 62:12345678901234567890123456789012345678901234567890123456789
+ 63:12345678901234567890123456789012345678901234567890123456789
+ 64:12345678901234567890123456789012345678901234567890123456789
+ 65:12345678901234567890123456789012345678901234567890123456789
+ 66:12345678901234567890123456789012345678901234567890123456789"
+
+# Now we need the version of the above string that expect will look
+# for. So, we need to convert all '\n' to '\r\n' and add a trailing
+# '\r\n'.
+regsub -all {\n} $test_string {\r\n} test_string2
+set test_string2 "$test_string2\\r\\n"
+
+proc proc_write_test {} {
+ global test test_string
+ set path "/proc/systemtap/$test/command"
+
+ proc_write_value $test $path $test_string
+ return 0;
+}
+
+set systemtap_write_script {
+ global iteration = 0
+ global saved_value[20]
+
+ probe procfs("command").write {
+ saved_value[iteration] = $value
+ iteration++
+ }
+
+ probe begin {
+ printf("systemtap starting probe\n")
+ }
+
+ probe end {
+ printf("systemtap ending probe\n")
+ for (i = 0; i < iteration; i++) {
+ printf("%s", saved_value[i])
+ }
+ }
+}
+
+# We're forcing the MAXSTRINGLEN to be 512 chars to make sure we know
+# what we're testing.
+stap_run $test proc_write_test $test_string2 -DMAXSTRINGLEN=512 \
+ -e $systemtap_write_script -m $test
+exec /bin/rm -f ${test}.ko