From 1456891d134d42f8067745ddf30185ff3b1520d6 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Wed, 6 Dec 2023 14:13:57 -0500 Subject: [PATCH] Resolves: RHEL-18334 --- .systemtap.metadata | 1 + RHEL-18334.patch | 147 ++++++++++++++++++++++++++++++++++++++++++++ systemtap.spec | 7 ++- 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 .systemtap.metadata create mode 100644 RHEL-18334.patch diff --git a/.systemtap.metadata b/.systemtap.metadata new file mode 100644 index 0000000..305e7a5 --- /dev/null +++ b/.systemtap.metadata @@ -0,0 +1 @@ +f44f1853ddd462ac97b2c7c4b3a9434440d9d9c2 systemtap-5.0.tar.gz diff --git a/RHEL-18334.patch b/RHEL-18334.patch new file mode 100644 index 0000000..4b1c536 --- /dev/null +++ b/RHEL-18334.patch @@ -0,0 +1,147 @@ +commit b84a5e8c2c5a857c0790a71df7824259a95131cf +Author: William Cohen +Date: Mon Dec 4 11:28:10 2023 -0500 + + PR31074: Ensure that the set_kernel_string* functions limit their writes + + Both the set_kernel_string and set_kernel_string_n function use the + underlying _stp_store_deref_string_ function to write strings. There + were two issues with the this function: + + 1) wrote MAXSTRINGLEN bytes even if string was shorter + 2) null write at end could spill past end of buffer + + The first issue was addressed by stopping to write once a null + character is encountered. The second issue is a side effect of C + implicit promotion of character constants to ints and was addressed by + explicitlying casting the character constants as a char. + + The pr31074.exp test was added to verify that the write length are + limited to string length and the null write does not go beyond the end + of the buffer. + +diff --git a/runtime/linux/loc2c-runtime.h b/runtime/linux/loc2c-runtime.h +index 68fbe2ab6..663360293 100644 +--- a/runtime/linux/loc2c-runtime.h ++++ b/runtime/linux/loc2c-runtime.h +@@ -1007,11 +1007,14 @@ static inline int _stp_store_deref_string_(char *src, void *addr, size_t len, + { + for (i = 0; i < len - 1; ++i) + { ++ if (*src == '\0') ++ break; + err = __stp_put_either(*src++, (u8 *)addr + i, seg); + if (err) + goto out; + } +- err = __stp_put_either('\0', (u8 *)addr + i, seg); ++ /* PR31074: cast (char) '\0' to make sure right size */ ++ err = __stp_put_either((char) '\0', (u8 *)addr + i, seg); + } + + out: +diff --git a/testsuite/systemtap.base/pr31074.exp b/testsuite/systemtap.base/pr31074.exp +new file mode 100644 +index 000000000..5b382b789 +--- /dev/null ++++ b/testsuite/systemtap.base/pr31074.exp +@@ -0,0 +1,5 @@ ++# Check that the set_kernel_* functions work correctly. ++ ++set test "pr31074" ++ ++stap_run $test no_load $all_pass_string -g $srcdir/$subdir/$test.stp +diff --git a/testsuite/systemtap.base/pr31074.stp b/testsuite/systemtap.base/pr31074.stp +new file mode 100644 +index 000000000..930c276b5 +--- /dev/null ++++ b/testsuite/systemtap.base/pr31074.stp +@@ -0,0 +1,88 @@ ++/* ++ * pr31074.stp ++ * ++ * Check that the set_kernel_string function work correctly. ++ */ ++ ++probe begin { println("systemtap starting probe") } ++probe end { println("systemtap ending probe") } ++ ++global errors = 0 ++ ++function assert_string(test, expected, value) ++{ ++ if (value == expected) ++ return 1 ++ printf("systemtap test failure - %s: expected \"%s\", got \"%s\"\n", ++ test, expected, value) ++ errors++ ++ return 0 ++} ++ ++function assert_not_reached(test) ++{ ++ printf("systemtap test failure - %s: missing exception\n", test) ++ errors++ ++} ++ ++function assert_buffer_untouched(test, addr) ++{ ++ if (!buffer_42(addr)) { ++ printf("systemtap test failure - %s: buffer overwritten\n", test) ++ errors++ ++ } ++} ++ ++ ++probe end(1) ++{ ++ test = "set_kernel_string" ++ addr3 = get_buffer3() ++ addr2 = get_buffer2() ++ if (assert_string(test, "", kernel_string(addr2))) { ++ set_kernel_string(addr2, "bar") ++ assert_string(test, "bar", kernel_string(addr2)) ++ } ++ addr1 = get_buffer1() ++ if (assert_string(test, "", kernel_string(addr1))) { ++ set_kernel_string(addr1, "foo") ++ assert_string(test, "foo", kernel_string(addr1)) ++ } ++ /* now check to make sure that "bar" has not been overwritten */ ++ assert_string("no null overrun", "bar", kernel_string(addr2)) ++ assert_buffer_untouched("no overrun", addr3) ++ if (!errors) ++ println("systemtap test success") ++} ++ ++%{ ++ static char buffer_x[4+4+MAXSTRINGLEN]; ++%} ++ ++function get_buffer1:long () %{ ++ static char *buffer1 = &(buffer_x[0]); ++ memset(buffer1, 0, 4); ++ STAP_RETVALUE = (long)buffer1; ++%} ++ ++function get_buffer2:long () %{ ++ static char *buffer2 = &(buffer_x[4]); ++ memset(buffer2, 0, 4); ++ STAP_RETVALUE = (long)buffer2; ++%} ++ ++function get_buffer3:long () %{ ++ static char *buffer3 = &(buffer_x[8]); ++ memset(buffer3, 42, MAXSTRINGLEN); ++ STAP_RETVALUE = (long)buffer3; ++%} ++ ++function buffer_42:long (addr:long) %{ ++ int i; ++ char *buffer3 = (char *)STAP_ARG_addr; ++ STAP_RETVALUE = 1; ++ for(i=0; i< MAXSTRINGLEN; ++i){ ++ if (buffer3[i] != 42) ++ STAP_RETVALUE = 0; ++ } ++%} diff --git a/systemtap.spec b/systemtap.spec index 3b7d78d..0d5b080 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -116,7 +116,7 @@ m stapdev stapdev Name: systemtap # PRERELEASE Version: 5.0 -Release: 3%{?release_override}%{?dist} +Release: 4%{?release_override}%{?dist} # for version, see also configure.ac @@ -154,6 +154,7 @@ URL: http://sourceware.org/systemtap/ Source: ftp://sourceware.org/pub/systemtap/releases/systemtap-%{version}.tar.gz Patch1: RHEL-16549.patch +Patch2: RHEL-18334.patch # Build* BuildRequires: make @@ -582,6 +583,7 @@ or within a container. %prep %setup -q %patch -P1 -p1 +%patch -P2 -p1 %build @@ -1301,6 +1303,9 @@ exit 0 # PRERELEASE %changelog +* Wed Dec 6 2023 William Cohen - 5.0-4 +- RHEL-18334 + * Tue Nov 14 2023 Frank Ch. Eigler - 5.0-3 - RHEL-16549