> [...] >>> + * On failure, it is filled with zeroes. > [...] > You fill it with 0x30's ... So sorry about this, I'll submit another revision to fix this. Thanks again for your preciseness and patience. Daniel Borkmann <daniel@xxxxxxxxxxxxx> 于2019年12月18日周三 上午3:39写道: > > On 12/17/19 5:29 PM, Yonghong Song wrote: > > On 12/17/19 1:47 AM, Wenbo Zhang wrote: > [...] > >> + * On failure, it is filled with zeroes. > [...] > >> */ > >> #define __BPF_FUNC_MAPPER(FN) \ > >> FN(unspec), \ > >> @@ -2938,7 +2964,8 @@ union bpf_attr { > >> FN(probe_read_user), \ > >> FN(probe_read_kernel), \ > >> FN(probe_read_user_str), \ > >> - FN(probe_read_kernel_str), > >> + FN(probe_read_kernel_str), \ > >> + FN(get_fd_path), > >> > >> /* integer value in 'imm' field of BPF_CALL instruction selects which helper > >> * function eBPF program intends to call > >> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c > >> index e5ef4ae9edb5..43a6aa6ad967 100644 > >> --- a/kernel/trace/bpf_trace.c > >> +++ b/kernel/trace/bpf_trace.c > >> @@ -762,6 +762,71 @@ static const struct bpf_func_proto bpf_send_signal_proto = { > >> .arg1_type = ARG_ANYTHING, > >> }; > >> > >> +BPF_CALL_3(bpf_get_fd_path, char *, dst, u32, size, int, fd) > >> +{ > >> + int ret = -EBADF; > >> + struct file *f; > >> + char *p; > >> + > >> + /* Ensure we're in user context which is safe for the helper to > >> + * run. This helper has no business in a kthread. > >> + */ > >> + if (unlikely(in_interrupt() || > >> + current->flags & (PF_KTHREAD | PF_EXITING))) { > >> + ret = -EPERM; > >> + goto error; > >> + } > >> + > >> + /* Use fget_raw instead of fget to support O_PATH, and it doesn't > >> + * have any sleepable code, so it's ok to be here. > >> + */ > >> + f = fget_raw(fd); > >> + if (!f) > >> + goto error; > >> + > >> + /* For unmountable pseudo filesystem, it seems to have no meaning > >> + * to get their fake paths as they don't have path, and to be no > >> + * way to validate this function pointer can be always safe to call > >> + * in the current context. > >> + */ > >> + if (f->f_path.dentry->d_op && f->f_path.dentry->d_op->d_dname) { > >> + ret = -EINVAL; > >> + fput(f); > >> + goto error; > >> + } > >> + > >> + /* After filter unmountable pseudo filesytem, d_path won't call > >> + * dentry->d_op->d_name(), the normally path doesn't have any > >> + * sleepable code, and despite it uses the current macro to get > >> + * fs_struct (current->fs), we've already ensured we're in user > >> + * context, so it's ok to be here. > >> + */ > >> + p = d_path(&f->f_path, dst, size); > >> + if (IS_ERR(p)) { > >> + ret = PTR_ERR(p); > >> + fput(f); > >> + goto error; > >> + } > >> + > >> + ret = strlen(p) + 1; > >> + memmove(dst, p, ret); > >> + fput(f); > >> + return ret; > >> + > >> +error: > >> + memset(dst, '0', size); > > You fill it with 0x30's ... > > >> + return ret; > >> +}