diff options
author | David Smith <dsmith@redhat.com> | 2010-01-26 13:40:51 -0600 |
---|---|---|
committer | David Smith <dsmith@redhat.com> | 2010-01-26 13:40:51 -0600 |
commit | 6390a48a6dfb88c9692af877e1767ce6cc8030d0 (patch) | |
tree | 3eee6e605f49701ace44f5c130db8b2cedcb6d3f | |
parent | 9f49a9853caff67bcc5de7dfe2c52ab1ae7f3738 (diff) | |
download | systemtap-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.cxx | 7 | ||||
-rw-r--r-- | testsuite/systemtap.base/procfs_write.exp | 135 |
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 |