rc = bpf_probe_read_str(buf, BPF_MAXSTRINGLEN, addr); */
alloc, $buf, BPF_MAXSTRINGLEN;
0x62, $buf, -, -, 0x0; /* stw [$buf+0], 0x0 -- guarantee NUL byte */
+ /* TODO PR25168: probe_read_str is used for both kernel and user memory.
+ BPF will soon deprecate these in favour of separate functions. */
call, $rc, probe_read_str, $buf, BPF_MAXSTRINGLEN, $addr;
/* if (rc < 0) return err_msg;
rc = bpf_probe_read_str(buf, n, addr); */
alloc, $buf, BPF_MAXSTRINGLEN;
0x62, $buf, -, -, 0x0; /* stw [buf+0], 0 -- guarantee NUL byte */
+ /* TODO PR25168: probe_read_str is used for both kernel and user memory.
+ BPF will soon deprecate these in favour of separate functions. */
call, $rc, probe_read_str, $buf, $n, $addr; /* TODO: should work if the helper is named bpf_probe_read_str() too */
/* if (rc < 0) error("...", addr); */
0x35, $rc, 0, _done, -; /* jge rc, 0, _done */
- call, -, printf, "ERROR: kernel string copy fault at 0x%p [man error::fault]", $addr; /* TODO document stapbpf version of error::fault */
+ call, -, printf, "ERROR: string copy fault at 0x%p [man error::fault]", $addr; /* TODO document stapbpf version of error::fault */
call, -, exit;
label, _done;
* when userspace data is not accessible at the given address.
*/
function user_string_n:string (addr:long, n:long)
+%( runtime != "bpf" %?
%( systemtap_v < "2.3" %? // PR15044
{ return user_string_n(addr, n, "<unknown>") }
%:
STAP_RETVALUE[len - 1] = '\0';
%}
%)
+%:
+ { /* pure */ /* bpf */
+ // TODO: Does not provide address in error message.
+ return user_string_n(addr, n, "user string copy fault")
+ }
+%)
/**
* sfunction user_string_n - Retrieves string of given length from user space
* address.
*/
function user_string_n:string (addr:long, n:long, err_msg:string)
+%( runtime != "bpf" %?
%{ /* pure */ /* myproc-unprivileged */ /* unmodified-fnargs */
int64_t len = clamp_t(int64_t, STAP_ARG_n + 1, 1, MAXSTRINGLEN - 1);
if (_stp_strncpy_from_user(STAP_RETVALUE,
else
STAP_RETVALUE[len - 1] = '\0';
%}
+%:
+ { /* pure */ /* bpf */
+ /* !!! ACHTUNG !!!
+ * bpf uses the same bpf_probe_read() helpers for kernel and user
+ * addresses, on the assumption that the address spaces coincide.
+ * Which only really works on x86_64 in Current Day.
+ *
+ * If the address space is changed, it may return the wrong data.
+ * TODO PR25168: Fix this as soon as BPF ships proper, separate
+ * bpf_probe_read_{user,kernel}() helpers.
+ */
+ %( arch == "x86_64" %?
+ // TODO: Does not use the provided err_msg.
+ return kernel_string_n(addr, n) // calls probe_read_str()
+ %:
+ // TODO: Use error() function.
+ print("ERROR(unsupported): %s", err_msg)
+ exit()
+ %)
+ }
+%)
function user_string_n2:string (addr:long, n:long, err_msg:string) {
return user_string_n(addr, n, err_msg);
}
* not abort) about the failure.
*/
function user_string_n_warn:string (addr:long, n:long, warn_msg:string)
+%( runtime != "bpf" %?
%{ /* pure */ /* myproc-unprivileged */ /* unmodified-fnargs */
int64_t len = clamp_t(int64_t, STAP_ARG_n + 1, 1, MAXSTRINGLEN - 1);
long rc;
} else
STAP_RETVALUE[len - 1] = '\0';
%}
+%:
+ { /* pure */ /* bpf */
+ /* !!! ACHTUNG !!!
+ * bpf uses the same bpf_probe_read() helpers for kernel and user
+ * addresses, on the assumption that the address spaces coincide.
+ * Which only really works on x86_64 in Current Day.
+ *
+ * If the address space is changed, it may return the wrong data.
+ * TODO PR25168: Fix this as soon as BPF ships proper, separate
+ * bpf_probe_read_{user,kernel}() helpers.
+ */
+ %( arch == "x86_64" %?
+ return kernel_string_n(addr, n, warn_msg) // calls probe_read_str()
+ %:
+ return warn_msg // don't even bother
+ %)
+ }
+%)
function user_string2_n_warn:string (addr:long, n:long, warn_msg:string) {
user_string_n_warn(addr, n, warn_msg);
}