• Gianluca Borello's avatar
    bpf: add bpf_probe_read_str helper · a5e8c070
    Gianluca Borello authored
    Provide a simple helper with the same semantics of strncpy_from_unsafe():
    
    int bpf_probe_read_str(void *dst, int size, const void *unsafe_addr)
    
    This gives more flexibility to a bpf program. A typical use case is
    intercepting a file name during sys_open(). The current approach is:
    
    SEC("kprobe/sys_open")
    void bpf_sys_open(struct pt_regs *ctx)
    {
    	char buf[PATHLEN]; // PATHLEN is defined to 256
    	bpf_probe_read(buf, sizeof(buf), ctx->di);
    
    	/* consume buf */
    }
    
    This is suboptimal because the size of the string needs to be estimated
    at compile time, causing more memory to be copied than often necessary,
    and can become more problematic if further processing on buf is done,
    for example by pushing it to userspace via bpf_perf_event_output(),
    since the real length of the string is unknown and the entire buffer
    must be copied (and defining an unrolled strnlen() inside the bpf
    program is a very inefficient and unfeasible approach).
    
    With the new helper, the code can easily operate on the actual string
    length rather than the buffer size:
    
    SEC("kprobe/sys_open")
    void bpf_sys_open(struct pt_regs *ctx)
    {
    	char buf[PATHLEN]; // PATHLEN is defined to 256
    	int res = bpf_probe_read_str(buf, sizeof(buf), ctx->di);
    
    	/* consume buf, for example push it to userspace via
    	 * bpf_perf_event_output(), but this time we can use
    	 * res (the string length) as event size, after checking
    	 * its boundaries.
    	 */
    }
    
    Another useful use case is when parsing individual process arguments or
    individual environment variables navigating current->mm->arg_start and
    current->mm->env_start: using this helper and the return value, one can
    quickly iterate at the right offset of the memory area.
    
    The code changes simply leverage the already existent
    strncpy_from_unsafe() kernel function, which is safe to be called from a
    bpf program as it is used in bpf_trace_printk().
    Signed-off-by: default avatarGianluca Borello <g.borello@gmail.com>
    Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    a5e8c070
bpf_trace.c 17.2 KB