Part of v0.2.0 (#32). Solves the sendfile blind spot surfaced by #37, so the detail panel body view (#35) actually shows bodies for static-file responses, not just dynamic ones.
Problem
tinytap captures payloads at the syscall layer via tracepoints (write/sendto/sendmsg/… — see #8 for why tracepoints, not kprobes). sendfile(2) (and splice(2)) send file contents kernel-to-kernel (page cache → socket) and never copy the bytes through user space. The syscall args are just (out_fd, in_fd, offset, count) — no data pointer. So the body is invisible.
This is not rare: nginx and Caddy serve static files via sendfile by default, and Go net/http also hits it — http.ServeFile/io.Copy fall into net.(*TCPConn).ReadFrom's sendfile fast path. Any of these → the response body simply doesn't appear.
Why a kprobe (and only here)
There is no tracepoint that carries the sendfile payload — the bytes never pass through a write syscall, and there is no stable tracepoint at the TCP send path with the data. The only vantage point is a kprobe on the kernel's TCP send path. This is not a revert of #8: the syscall layer stays on tracepoints; this adds a kprobe at a different layer (TCP internals) that tracepoints don't cover, isolated as an optional capture source.
Note what stays on tracepoints (separate, simpler work, not this issue): writev/readv content (sys_enter_writev) and the sendfile metadata — size/fds — via sys_enter_sendfile64. Only the sendfile body bytes force a kprobe.
Scope
Out of scope
writev/readv capture and sendfile metadata — tracepoint-only, separate issue
- TLS (sendfile of encrypted data is still ciphertext at this layer) — v0.4
- TC/sockmap-based whole-stream capture — a different architecture, not chosen here
Done when
- A static-file response served via sendfile (nginx, Caddy, or Go
http.ServeFile) shows its body in the detail panel, within the payload cap
- Works across the
tcp_sendpage and MSG_SPLICE_PAGES kernel eras (or cleanly skips on unsupported kernels with a logged note)
- The kprobe path is isolated so the tracepoint capture is unaffected when it's disabled or unavailable
Refs: #37 (discovered the gap), #36 (payload sample cap), #8 (tracepoint-vs-kprobe decision), #35 (body view this feeds).
Part of v0.2.0 (#32). Solves the sendfile blind spot surfaced by #37, so the detail panel body view (#35) actually shows bodies for static-file responses, not just dynamic ones.
Problem
tinytap captures payloads at the syscall layer via tracepoints (
write/sendto/sendmsg/… — see #8 for why tracepoints, not kprobes).sendfile(2)(andsplice(2)) send file contents kernel-to-kernel (page cache → socket) and never copy the bytes through user space. The syscall args are just(out_fd, in_fd, offset, count)— no data pointer. So the body is invisible.This is not rare: nginx and Caddy serve static files via sendfile by default, and Go
net/httpalso hits it —http.ServeFile/io.Copyfall intonet.(*TCPConn).ReadFrom's sendfile fast path. Any of these → the response body simply doesn't appear.Why a kprobe (and only here)
There is no tracepoint that carries the sendfile payload — the bytes never pass through a write syscall, and there is no stable tracepoint at the TCP send path with the data. The only vantage point is a kprobe on the kernel's TCP send path. This is not a revert of #8: the syscall layer stays on tracepoints; this adds a kprobe at a different layer (TCP internals) that tracepoints don't cover, isolated as an optional capture source.
Note what stays on tracepoints (separate, simpler work, not this issue):
writev/readvcontent (sys_enter_writev) and the sendfile metadata — size/fds — viasys_enter_sendfile64. Only the sendfile body bytes force a kprobe.Scope
tcp_sendpage/do_tcp_sendpages(page-based)->sendpageremoved; sendfile routes throughtcp_sendmsg_lockedwithMSG_SPLICE_PAGES, payload asITER_BVEC(kernel pages)bpf_probe_read_kernelfrom the page contents.struct sock*, not the user fd. Decide how to key the event so it joins the existing(pid, fd)pairer — e.g. map sock→fd, or extend the pairer key. Verify pid is valid (sendfile runs in process syscall context).vmlinux.h, CO-RE, arch-sensitive struct reads, version-specific probes — so keep it self-contained and guarded.Out of scope
writev/readvcapture and sendfile metadata — tracepoint-only, separate issueDone when
http.ServeFile) shows its body in the detail panel, within the payload captcp_sendpageandMSG_SPLICE_PAGESkernel eras (or cleanly skips on unsupported kernels with a logged note)Refs: #37 (discovered the gap), #36 (payload sample cap), #8 (tracepoint-vs-kprobe decision), #35 (body view this feeds).