]> sourceware.org Git - systemtap.git/commitdiff
Flip user_string_n_quoted to limit the input count
authorJosh Stone <jistone@redhat.com>
Thu, 31 Oct 2013 22:03:34 +0000 (15:03 -0700)
committerJosh Stone <jistone@redhat.com>
Fri, 1 Nov 2013 07:13:40 +0000 (00:13 -0700)
The documentation of that function implies that it's counting n from the
input string, but in fact that limit was being applied to the output,
including quotes and escaping.

Now _stp_text_str takes two length parameters to limit the input count
and output size separately.  A new user_string_n2_quoted() lets you
specify both of these lengths, and user_string_n_quoted now uses that to
limit input length, or output still in compatibility mode.

Several syscall tapsets which read user buffers of known length will now
use user_string_n2_quoted to fit that.  This was seen in syscall.write
which may not necessarily have any '\0' at the end of its buffer.

runtime/stp_string.c
runtime/stp_string.h
tapset/linux/nd_syscalls.stp
tapset/linux/nd_syscalls2.stp
tapset/linux/syscalls.stp
tapset/linux/syscalls2.stp
tapset/string.stp
tapset/uconversions.stp
testsuite/buildok/conversions-embedded.stp

index a7392782e8fcff675dd7913eb4291ca0cf73d265..8a20b13efffd84404a25c00a589c12a74fd23dda 100644 (file)
@@ -58,20 +58,23 @@ static int _stp_vscnprintf(char *buf, size_t size, const char *fmt, va_list args
  *
  * @param outstr Output string pointer
  * @param in Input string pointer
- * @param len Maximum length of string to return not including terminating 0.
+ * @param inlen Maximum length of string to read not including terminating 0.
+ * @param outlen Maximum length of string to return not including terminating 0.
  * 0 means MAXSTRINGLEN.
  * @param quoted Put double quotes around the string. If input string is truncated
  * in will have "..." after the second quote.
  * @param user Set this to indicate the input string pointer is a userspace pointer.
  */
-static int _stp_text_str(char *outstr, char *in, int len, int quoted, int user)
+static int _stp_text_str(char *outstr, char *in, int inlen, int outlen, int quoted, int user)
 {
        char c = '\0', *out = outstr;
 
-       if (len <= 0 || len > MAXSTRINGLEN-1)
-               len = MAXSTRINGLEN-1;
+       if (inlen <= 0 || inlen > MAXSTRINGLEN-1)
+               inlen = MAXSTRINGLEN-1;
+       if (outlen <= 0 || outlen > MAXSTRINGLEN-1)
+               outlen = MAXSTRINGLEN-1;
        if (quoted) {
-               len = max(len, 5) - 2;
+               outlen = max(outlen, 5) - 2;
                *out++ = '"';
        }
 
@@ -81,7 +84,7 @@ static int _stp_text_str(char *outstr, char *in, int len, int quoted, int user)
        } else
                c = *in;
 
-       while (c && len > 0) {
+       while (c && inlen > 0 && outlen > 0) {
                int num = 1;
                if (isprint(c) && isascii(c)
                     && c != '"' && c != '\\') /* quoteworthy characters */
@@ -104,7 +107,7 @@ static int _stp_text_str(char *outstr, char *in, int len, int quoted, int user)
                                break;
                        }
                        
-                       if (len < num)
+                       if (outlen < num)
                                break;
 
                        *out++ = '\\';
@@ -143,7 +146,8 @@ static int _stp_text_str(char *outstr, char *in, int len, int quoted, int user)
                                break;
                        }
                }
-               len -= num;
+               outlen -= num;
+               inlen--;
                in++;
                if (user) {
                        if (_stp_read_address(c, in, USER_DS))
@@ -153,8 +157,8 @@ static int _stp_text_str(char *outstr, char *in, int len, int quoted, int user)
        }
 
        if (quoted) {
-               if (c) {
-                       out = out - 3 + len;
+               if (c && inlen > 0) {
+                       out = out - 3 + outlen;
                        *out++ = '"';
                        *out++ = '.';
                        *out++ = '.';
@@ -165,7 +169,7 @@ static int _stp_text_str(char *outstr, char *in, int len, int quoted, int user)
        *out = '\0';
        return 0;
 bad:
-       strlcpy (outstr, "<unknown>", len);
+       strlcpy (outstr, "<unknown>", outlen);
        return -1; // PR15044
 }
 
index e60db237ca3e34d1efcf0737fc12101746607834..054d7da46d584a4638cef9ece7d0af65a4f6b8bf 100644 (file)
@@ -10,7 +10,7 @@
 #define _STP_STRING_H_
 
 #define to_oct_digit(c) ((c) + '0')
-static int _stp_text_str(char *out, char *in, int len, int quoted, int user);
+static int _stp_text_str(char *out, char *in, int inlen, int outlen, int quoted, int user);
 
 
 #if defined(__KERNEL__)
index 5cb7ac26f8415c6398e394118acbcdeb8868b793..f2daa011624d60cff4e220cbb8b8f9df6ba7785b 100644 (file)
@@ -135,7 +135,7 @@ probe nd_syscall.add_key = kprobe.function("sys_add_key") ?
        argstr = sprintf("%s, %s, %s, %d, %d",
                user_string_quoted(type_uaddr),
                user_string_quoted(description_uaddr),
-               user_string_n_quoted(payload_uaddr, syscall_string_trunc),
+               user_string_n2_quoted(payload_uaddr, plen, syscall_string_trunc),
                plen, ringid)
 }
 probe nd_syscall.add_key.return = kprobe.function("sys_add_key").return ?
index 0103f2bbc7ee01745966b8fd5f52fc441634acbb..667393c15dff295b422d002ae2ed1cf467c091a6 100644 (file)
@@ -709,7 +709,7 @@ probe nd_syscall.pwrite = kprobe.function("sys_pwrite64") ?
        count = ulong_arg(3)
        offset = longlong_arg(4)
        argstr = sprintf("%d, %s, %d, %d", fd,
-                       user_string_n_quoted(buf_uaddr, syscall_string_trunc),
+                       user_string_n2_quoted(buf_uaddr, count, syscall_string_trunc),
                                count, offset)
 }
 probe nd_syscall.pwrite.return = kprobe.function("sys_pwrite64").return ?
@@ -743,7 +743,7 @@ probe nd_syscall.pwrite32 = kprobe.function("sys32_pwrite64") ?
        count = ulong_arg(3)
        offset = (u32_arg(4) << 32) + u32_arg(5)
        argstr = sprintf("%d, %s, %d, %d", fd,
-                       user_string_n_quoted(buf_uaddr, syscall_string_trunc),
+                       user_string_n2_quoted(buf_uaddr, count, syscall_string_trunc),
                                count, offset)
 }
 probe nd_syscall.pwrite32.return = kprobe.function("sys32_pwrite64").return ?
@@ -4500,7 +4500,9 @@ probe nd_syscall.write = kprobe.function("sys_write") ?
        fd = uint_arg(1)
        buf_uaddr = pointer_arg(2)
        count = ulong_arg(3)
-       argstr = sprintf("%d, %s, %d", fd, user_string_n_quoted(buf_uaddr, syscall_string_trunc), count)
+       argstr = sprintf("%d, %s, %d", fd,
+               user_string_n2_quoted(buf_uaddr, count, syscall_string_trunc),
+               count)
 
 }
 probe nd_syscall.write.return = kprobe.function("sys_write").return ?
index 5f63f88c7fdc8c7163142a481eb368c84678ad15..13fb92fd94dd5a86e6b08852f63d8b686b094351 100644 (file)
@@ -107,7 +107,7 @@ probe syscall.add_key = kernel.function("sys_add_key").call ?
        argstr = sprintf("%s, %s, %s, %d, %d",
                user_string_quoted($_type),
                user_string_quoted($_description),
-               user_string_n_quoted($_payload, syscall_string_trunc),
+               user_string_n2_quoted($_payload, $plen, syscall_string_trunc),
                $plen, $ringid)
 }
 probe syscall.add_key.return = kernel.function("sys_add_key").return ?
index 083fa1c2909bc22238e88139cc19e22f3eca11c6..6770a3effecdba4b95cfb2890e8a0cac7d6c38e4 100644 (file)
@@ -612,7 +612,7 @@ probe syscall.pwrite = kernel.function("sys_pwrite64").call
        count = $count
        offset = $pos
        argstr = sprintf("%d, %s, %d, %d", $fd,
-               user_string_n_quoted($buf, syscall_string_trunc),
+               user_string_n2_quoted($buf, $count, syscall_string_trunc),
                $count, $pos)
 }
 probe syscall.pwrite.return = kernel.function("sys_pwrite64").return
@@ -631,12 +631,12 @@ probe syscall.pwrite32 = kernel.function("sys32_pwrite64").call ?
 %( arch == "s390" %?
        buf_uaddr = $ubuf
        argstr = sprintf("%d, %s, %d, %d", $fd,
-               user_string_n_quoted($ubuf, syscall_string_trunc),
+               user_string_n2_quoted($ubuf, $count, syscall_string_trunc),
                $count, ($poshi << 32) + $poslo)
 %:
        buf_uaddr = $buf
        argstr = sprintf("%d, %s, %d, %d", $fd,
-               user_string_n_quoted($buf, syscall_string_trunc),
+               user_string_n2_quoted($buf, $count, syscall_string_trunc),
                $count, ($poshi << 32) + $poslo)
 %)
 }
@@ -3651,7 +3651,9 @@ probe syscall.write = kernel.function("sys_write").call
        fd = $fd
        buf_uaddr = $buf
        count = $count
-       argstr = sprintf("%d, %s, %d", $fd, user_string_n_quoted($buf, syscall_string_trunc), $count)
+       argstr = sprintf("%d, %s, %d", $fd,
+               user_string_n2_quoted($buf, $count, syscall_string_trunc),
+               $count)
 }
 probe syscall.write.return = kernel.function("sys_write").return
 {
index f8376a32f36a17d1a1dbdadbb173d03bfb2314c9..05dcb4a19d43c91fa2b6668567e4085067f9ed00 100644 (file)
@@ -85,7 +85,7 @@ function isinstr:long(s1:string,s2:string) %{ /* pure */ /* unprivileged */
  */
 function text_str:string(input:string) 
 %{ /* pure */ /* unprivileged */
-       if (_stp_text_str(STAP_RETVALUE, STAP_ARG_input, 0, 0, 0) < 0) {
+       if (_stp_text_str(STAP_RETVALUE, STAP_ARG_input, 0, 0, 0, 0) < 0) {
                STAP_RETVALUE[0] = '\0';
        }
 %}
@@ -107,7 +107,7 @@ function text_strn:string(input:string, len:long, quoted:long)
 %{ /* pure */ /* unprivileged */
        int64_t len = clamp_t(int64_t, STAP_ARG_len, 0, MAXSTRINGLEN);
        if (_stp_text_str(
-                       STAP_RETVALUE, STAP_ARG_input, len, STAP_ARG_quoted, 0) < 0) {
+                       STAP_RETVALUE, STAP_ARG_input, 0, len, STAP_ARG_quoted, 0) < 0) {
                STAP_RETVALUE[0] = '\0';
        }
 %}
index 1850e2b8cec9fc1661dc7a80e1827c7ff95b9699..0903b693893cfddcdcfb0b6d68a61e8873582137 100644 (file)
@@ -104,7 +104,7 @@ function user_string2_warn:string (addr:long, warn_msg:string) {
  * returned as a string, without double quotes.
  */
 function user_string_quoted:string (addr:long) {
-       return user_string_n_quoted(addr, @MAXSTRINGLEN)
+       return user_string_n2_quoted(addr, @MAXSTRINGLEN, @MAXSTRINGLEN)
 }
 
 /**
@@ -221,10 +221,35 @@ function user_string2_n_warn:string (addr:long, n:long, warn_msg:string)
  * On the rare cases when userspace data is not accessible at the given address,
  * the address itself is returned as a string, without double quotes.
  */
-function user_string_n_quoted:string (addr:long, n:long)
+function user_string_n_quoted:string (addr:long, n:long) {
+%(systemtap_v < "2.4" %?
+       // We used to count n by output characters
+       return user_string_n2_quoted(addr, @MAXSTRINGLEN, n)
+%:
+       return user_string_n2_quoted(addr, n, @MAXSTRINGLEN)
+%)
+}
+
+/**
+ * sfunction user_string_n2_quoted - Retrieves and quotes string from user space
+ *
+ * @addr: the user space address to retrieve the string from
+ * @inlen: the maximum length of the string to read (if not null terminated)
+ * @outlen: the maximum length of the output string
+ *
+ * Description: Reads up to inlen characters of a C string from the given user
+ * space memory address, and returns up to outlen characters, where any ASCII
+ * characters that are not printable are replaced by the corresponding escape
+ * sequence in the returned string. Note that the string will be surrounded by
+ * double quotes.  On the rare cases when userspace data is not accessible at
+ * the given address, the address itself is returned as a string, without
+ * double quotes.
+ */
+function user_string_n2_quoted:string (addr:long, inlen:long, outlen:long)
 %{ /* pure */ /* myproc-unprivileged */
        // Note the lack of STAP_ARG_n+1 as in other funcs() -- PR15617
-       int64_t len = clamp_t(int64_t, STAP_ARG_n, 0, MAXSTRINGLEN);
+       int64_t inlen = clamp_t(int64_t, STAP_ARG_inlen, 0, MAXSTRINGLEN);
+       int64_t outlen = clamp_t(int64_t, STAP_ARG_outlen, 0, MAXSTRINGLEN);
        if (STAP_ARG_addr == 0)
 #if STAP_COMPAT_VERSION < STAP_VERSION(2,3) // PR15044
                strlcpy(STAP_RETVALUE, "NULL", MAXSTRINGLEN);
@@ -233,7 +258,7 @@ function user_string_n_quoted:string (addr:long, n:long)
 #endif
        else {
                int rc = _stp_text_str(STAP_RETVALUE,
-                       (char *)(uintptr_t)STAP_ARG_addr, len, 1, 1);
+                       (char *)(uintptr_t)STAP_ARG_addr, inlen, outlen, 1, 1);
                if (rc < 0)
 #if STAP_COMPAT_VERSION < STAP_VERSION(2,3) // PR15044
                        strlcpy(STAP_RETVALUE, "<unknown>", MAXSTRINGLEN);
index 00a9bccc7d13894e16d6270578d5c455ae6d0370..20fd5d3e2f65c56f01e13bce64b535c4be7e19f4 100755 (executable)
@@ -20,6 +20,7 @@ probe begin {
        print (user_string_n2(0, 5, "foobar"))
        print (user_string_n_warn(0, 0))
        print (user_string_n_quoted(0, 0))
+       print (user_string_n2_quoted(0, 0, 0))
        print (user_string_utf32 (0))
        print (user_string_utf16 (0))
        print (user_short(0))
This page took 0.039096 seconds and 5 git commands to generate.