> On Sat, Nov 23, 2019 at 05:35:14AM +0000, Al Viro wrote: > > On Fri, Nov 22, 2019 at 09:19:21PM -0800, Alexei Starovoitov wrote: > > > > > hard to tell. It will be run out of bpf prog that attaches to kprobe or > > > tracepoint. What is the concern about locking? > > > d_path() doesn't take any locks and doesn't depend on any locks. Above 'if' > > > checks that plain d_path() is used and not some specilized callback with > > > unknown logic. > > > > It sure as hell does. It might end up taking rename_lock and/or mount_lock > > spinlock components. It'll try not to, but if the first pass ends up with > > seqlock mismatch, it will just grab the spinlock the second time around. > ohh. got it. I missed _or_lock() part in there. > The need_seqretry() logic is tricky. afaics there is no way for the checks > outside of prepend_path() to prevent spin_lock to happen. And adding a flag to > prepend_path() to return early if retry is needed is too ugly. So this helper > won't be safe to be run out of kprobe. But if we allow it for tracepoints only > it should be ok. I think. There are no tracepoints in inner guts of vfs and I > don't think they will ever be. So running in tracepoint->bpf_prog->d_path we > will be sure that rename_lock+mount_lock can be safely spinlocked. Am I missing > something? Hi Alexei, Would you please give me an example of a deadlock condition under kprobe+bpf? I'm not familiar with this detail and want to learn more. > Above 'if's are not enough to make sure that it won't dead lock. > Allowing it in tracing_func_proto() means that it's available to kprobe too. > Hence deadlock is possible. Please see previous email thread. > This helper is safe in tracepoint+bpf only. So I should move it to `tp_prog_prog_func_proto` and `raw_tp_prog_func_prog` right? Is raw tracepoint+bpf safe? Thank you. Alexei Starovoitov <alexei.starovoitov@xxxxxxxxx> 于2019年12月5日周四 下午3:19写道: > > On Wed, Dec 04, 2019 at 11:20:35PM -0500, Wenbo Zhang wrote: > > > > +BPF_CALL_3(bpf_get_file_path, char *, dst, u32, size, int, fd) > > +{ > > + struct file *f; > > + char *p; > > + int ret = -EBADF; > > + > > + /* 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); > > Above 'if's are not enough to make sure that it won't dead lock. > Allowing it in tracing_func_proto() means that it's available to kprobe too. > Hence deadlock is possible. Please see previous email thread. > This helper is safe in tracepoint+bpf only. >