From f75409719f120a3dbee66d761cf23a64092d1414 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 28 Jan 2010 21:00:58 -0800 Subject: PR11234: Ensure __get_argv doesn't overflow That function was calling strlcpy as if the return value was the number of bytes copied, but strlcpy actually returns the length of the input string. We now use min() to handle the case when it's bigger than the buffer length, and drop out of the loop when that happens. --- testsuite/systemtap.base/overflow-get_argv.stp | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 testsuite/systemtap.base/overflow-get_argv.stp (limited to 'testsuite/systemtap.base/overflow-get_argv.stp') diff --git a/testsuite/systemtap.base/overflow-get_argv.stp b/testsuite/systemtap.base/overflow-get_argv.stp new file mode 100644 index 00000000..a4d1d212 --- /dev/null +++ b/testsuite/systemtap.base/overflow-get_argv.stp @@ -0,0 +1,62 @@ +// PR11234: __get_argv can overflow its return buffer + +// __get_argv has a signature like this: +// struct function___get_argv_locals { +// int64_t a; +// int64_t first; +// string_t __retvalue; +// } function___get_argv; +// +// These functions are meant to have an overlap such that we can tell if +// __get_argv overran its __retvalue. +// +// int64_t x; +// int64_t y; +// string_t z; +// string_t __retvalue; +// +// NB: __retvalue[0] always gets cleared on call, but the rest should be +// untouched, so we can use it as a sentinal. + +function clear:string(x:long, y:long, z:string) %{ + memset(THIS->__retvalue, 0, MAXSTRINGLEN); +%} + +function check:string(x:long, y:long, z:string) %{ + int i, bad; + for (i=1; i__retvalue[i]) + ++bad; + + if (bad) + snprintf(THIS->__retvalue, MAXSTRINGLEN, "%d non-zero bytes", bad); + else + strlcpy(THIS->__retvalue, "ok", MAXSTRINGLEN); +%} + +global result = "untested" + +probe syscall.execve { + if (pid() != target()) + next + + clear(0, 0, "") + foo = __get_argv($argv, 0) + result = check(0, 0, "") + + // ensure that foo isn't optimized away + if (foo == "foo") + next +} + +probe begin { + println("systemtap starting probe") +} + +probe end { + println("systemtap ending probe") + if (result == "ok") + println("systemtap test success") + else + println("systemtap test failure: ", result) +} -- cgit From 0daf3783cb8baaa114c02acbb9e6a241fcc39ed8 Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Mon, 1 Feb 2010 10:31:37 +0800 Subject: Fix uninitialization error on gcc 4.1.x * testsuite/systemtap.base/overflow-get_argv.stp: Initialize var. --- testsuite/systemtap.base/overflow-get_argv.stp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'testsuite/systemtap.base/overflow-get_argv.stp') diff --git a/testsuite/systemtap.base/overflow-get_argv.stp b/testsuite/systemtap.base/overflow-get_argv.stp index a4d1d212..159ef4a8 100644 --- a/testsuite/systemtap.base/overflow-get_argv.stp +++ b/testsuite/systemtap.base/overflow-get_argv.stp @@ -23,7 +23,7 @@ function clear:string(x:long, y:long, z:string) %{ %} function check:string(x:long, y:long, z:string) %{ - int i, bad; + int i, bad = 0; for (i=1; i__retvalue[i]) ++bad; -- cgit