Blob Blame History Raw
commit 3b2cf9012d600bf61aaeff855e9dc95200859b1d
Author: Serhei Makarov <smakarov@redhat.com>
Date:   Tue Apr 10 14:40:19 2018 -0400

    RHBZ1563052: fix off-by-one error in loc2c-runtime.h
    
    The new version of kderef_string (added along with the new eBPF
    runtime) copies an additional character compared to the old version.
    
    * runtime/linux/loc2c-runtime.h (_stp_deref_string_nofault): reduce len by 1 to leave room for NUL terminator.
    * testsuite/systemtap.base/set_kernel.stp: testcase for this bug.

diff --git a/runtime/linux/loc2c-runtime.h b/runtime/linux/loc2c-runtime.h
index 39dece0..fd736bd 100644
--- a/runtime/linux/loc2c-runtime.h
+++ b/runtime/linux/loc2c-runtime.h
@@ -722,7 +722,7 @@ static inline char *kderef_buffer_(char *dst, void *addr, size_t len)
  *
  * dst: read the string into this address
  * addr: address to read from
- * len: maximum number of bytes to read
+ * len: maximum number of bytes to store in dst, including the trailing NUL
  * seg: memory segment to use, either kernel (KERNEL_DS) or user
  * (USER_DS)
  * 
@@ -745,7 +745,8 @@ static inline long _stp_deref_string_nofault(char *dst, const char *addr,
     err = 1;
   else
     {
-      for (i = 0; i < len; ++i)
+      /* Reduce len by 1 to leave room for '\0' terminator. */
+      for (i = 0; i + 1 < len; ++i)
 	{
 	  u8 v;
 	  err = __stp_get_user(v, (u8 *)addr + i);
diff --git a/testsuite/systemtap.base/set_kernel.stp b/testsuite/systemtap.base/set_kernel.stp
index 729b477..dc93582 100644
--- a/testsuite/systemtap.base/set_kernel.stp
+++ b/testsuite/systemtap.base/set_kernel.stp
@@ -62,6 +62,20 @@ probe end(1)
         assert_not_reached(test)
     } catch {}
 
+    /* Be sure to also test in the other direction: */
+    test = "kernel_string_n"
+    addr = get_buffer()
+    if (assert_string(test, "", kernel_string_n(addr, 0))) {
+        set_kernel_string_n(addr, 7, "potatoe")
+        if (assert_string(test, "potatoe", kernel_string_n(addr, 7))) {
+            assert_string(test, "potato", kernel_string_n(addr, 6))
+        }
+    }
+    try {
+        println(kernel_string_n(-1, 10))
+        assert_not_reached(test)
+    } catch {}
+
     test = "set_kernel_long"
     addr = get_buffer()
     long_val = %( CONFIG_64BIT == "y" %? 0x123456789ABCDEF0 %: 0x12345678 %)