*
* @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++ = '"';
}
} 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 */
break;
}
- if (len < num)
+ if (outlen < num)
break;
*out++ = '\\';
break;
}
}
- len -= num;
+ outlen -= num;
+ inlen--;
in++;
if (user) {
if (_stp_read_address(c, in, USER_DS))
}
if (quoted) {
- if (c) {
- out = out - 3 + len;
+ if (c && inlen > 0) {
+ out = out - 3 + outlen;
*out++ = '"';
*out++ = '.';
*out++ = '.';
*out = '\0';
return 0;
bad:
- strlcpy (outstr, "<unknown>", len);
+ strlcpy (outstr, "<unknown>", outlen);
return -1; // PR15044
}
#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__)
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 ?
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 ?
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 ?
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 ?
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 ?
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
%( 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)
%)
}
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
{
*/
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';
}
%}
%{ /* 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';
}
%}
* 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)
}
/**
* 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);
#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);
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))