diff mbox series

[v9,bpf-next,10/14] bpf: Add d_path helper

Message ID 20200801170322.75218-11-jolsa@kernel.org
State Changes Requested
Delegated to: BPF Maintainers
Headers show
Series bpf: Add d_path helper | expand

Commit Message

Jiri Olsa Aug. 1, 2020, 5:03 p.m. UTC
Adding d_path helper function that returns full path for
given 'struct path' object, which needs to be the kernel
BTF 'path' object. The path is returned in buffer provided
'buf' of size 'sz' and is zero terminated.

  bpf_d_path(&file->f_path, buf, size);

The helper calls directly d_path function, so there's only
limited set of function it can be called from. Adding just
very modest set for the start.

Updating also bpf.h tools uapi header and adding 'path' to
bpf_helpers_doc.py script.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 include/uapi/linux/bpf.h       | 13 +++++++++
 kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
 scripts/bpf_helpers_doc.py     |  2 ++
 tools/include/uapi/linux/bpf.h | 13 +++++++++
 4 files changed, 76 insertions(+)

Comments

Alexei Starovoitov Aug. 2, 2020, 3:13 a.m. UTC | #1
On Sat, Aug 01, 2020 at 07:03:18PM +0200, Jiri Olsa wrote:
> Adding d_path helper function that returns full path for
> given 'struct path' object, which needs to be the kernel
> BTF 'path' object. The path is returned in buffer provided
> 'buf' of size 'sz' and is zero terminated.
> 
>   bpf_d_path(&file->f_path, buf, size);
> 
> The helper calls directly d_path function, so there's only
> limited set of function it can be called from. Adding just
> very modest set for the start.
> 
> Updating also bpf.h tools uapi header and adding 'path' to
> bpf_helpers_doc.py script.
> 
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  include/uapi/linux/bpf.h       | 13 +++++++++
>  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
>  scripts/bpf_helpers_doc.py     |  2 ++
>  tools/include/uapi/linux/bpf.h | 13 +++++++++
>  4 files changed, 76 insertions(+)
> 
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index eb5e0c38eb2c..a356ea1357bf 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -3389,6 +3389,18 @@ union bpf_attr {
>   *		A non-negative value equal to or less than *size* on success,
>   *		or a negative error in case of failure.
>   *
> + * int bpf_d_path(struct path *path, char *buf, u32 sz)

Please make it return 'long'. As you well ware the generated code will be better.
Jiri Olsa Aug. 2, 2020, 6:26 p.m. UTC | #2
On Sat, Aug 01, 2020 at 08:13:42PM -0700, Alexei Starovoitov wrote:
> On Sat, Aug 01, 2020 at 07:03:18PM +0200, Jiri Olsa wrote:
> > Adding d_path helper function that returns full path for
> > given 'struct path' object, which needs to be the kernel
> > BTF 'path' object. The path is returned in buffer provided
> > 'buf' of size 'sz' and is zero terminated.
> > 
> >   bpf_d_path(&file->f_path, buf, size);
> > 
> > The helper calls directly d_path function, so there's only
> > limited set of function it can be called from. Adding just
> > very modest set for the start.
> > 
> > Updating also bpf.h tools uapi header and adding 'path' to
> > bpf_helpers_doc.py script.
> > 
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  include/uapi/linux/bpf.h       | 13 +++++++++
> >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> >  scripts/bpf_helpers_doc.py     |  2 ++
> >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> >  4 files changed, 76 insertions(+)
> > 
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index eb5e0c38eb2c..a356ea1357bf 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -3389,6 +3389,18 @@ union bpf_attr {
> >   *		A non-negative value equal to or less than *size* on success,
> >   *		or a negative error in case of failure.
> >   *
> > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> 
> Please make it return 'long'. As you well ware the generated code will be better.
> 

will do, thanks

jirka
Andrii Nakryiko Aug. 5, 2020, 6:35 a.m. UTC | #3
On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding d_path helper function that returns full path for
> given 'struct path' object, which needs to be the kernel
> BTF 'path' object. The path is returned in buffer provided
> 'buf' of size 'sz' and is zero terminated.
>
>   bpf_d_path(&file->f_path, buf, size);
>
> The helper calls directly d_path function, so there's only
> limited set of function it can be called from. Adding just
> very modest set for the start.
>
> Updating also bpf.h tools uapi header and adding 'path' to
> bpf_helpers_doc.py script.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  include/uapi/linux/bpf.h       | 13 +++++++++
>  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
>  scripts/bpf_helpers_doc.py     |  2 ++
>  tools/include/uapi/linux/bpf.h | 13 +++++++++
>  4 files changed, 76 insertions(+)
>
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index eb5e0c38eb2c..a356ea1357bf 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -3389,6 +3389,18 @@ union bpf_attr {
>   *             A non-negative value equal to or less than *size* on success,
>   *             or a negative error in case of failure.
>   *
> + * int bpf_d_path(struct path *path, char *buf, u32 sz)

nit: probably would be good to do `const struct path *` here, even if
we don't do const-ification properly in all helpers.

> + *     Description
> + *             Return full path for given 'struct path' object, which
> + *             needs to be the kernel BTF 'path' object. The path is
> + *             returned in buffer provided 'buf' of size 'sz' and

typo: in the provided buffer 'buf' of size ... ?

> + *             is zero terminated.
> + *
> + *     Return
> + *             On success, the strictly positive length of the string,
> + *             including the trailing NUL character. On error, a negative
> + *             value.
> + *
>   */
>  #define __BPF_FUNC_MAPPER(FN)          \
>         FN(unspec),                     \
> @@ -3533,6 +3545,7 @@ union bpf_attr {
>         FN(skc_to_tcp_request_sock),    \
>         FN(skc_to_udp6_sock),           \
>         FN(get_task_stack),             \
> +       FN(d_path),                     \
>         /* */
>
>  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> index cb91ef902cc4..02a76e246545 100644
> --- a/kernel/trace/bpf_trace.c
> +++ b/kernel/trace/bpf_trace.c
> @@ -1098,6 +1098,52 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = {
>         .arg1_type      = ARG_ANYTHING,
>  };
>
> +BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz)
> +{
> +       int len;
> +       char *p;
> +
> +       if (!sz)
> +               return -ENAMETOOLONG;

if we are modeling this after bpf_probe_read_str(), sz == 0 returns
success and just does nothing. I don't think anyone will ever handle
or expect this error. I'd just return 0.


> +
> +       p = d_path(path, buf, sz);
> +       if (IS_ERR(p)) {
> +               len = PTR_ERR(p);
> +       } else {
> +               len = buf + sz - p;
> +               memmove(buf, p, len);
> +       }
> +
> +       return len;
> +}
> +

[...]
Jiri Olsa Aug. 5, 2020, 5:58 p.m. UTC | #4
On Tue, Aug 04, 2020 at 11:35:53PM -0700, Andrii Nakryiko wrote:
> On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding d_path helper function that returns full path for
> > given 'struct path' object, which needs to be the kernel
> > BTF 'path' object. The path is returned in buffer provided
> > 'buf' of size 'sz' and is zero terminated.
> >
> >   bpf_d_path(&file->f_path, buf, size);
> >
> > The helper calls directly d_path function, so there's only
> > limited set of function it can be called from. Adding just
> > very modest set for the start.
> >
> > Updating also bpf.h tools uapi header and adding 'path' to
> > bpf_helpers_doc.py script.
> >
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  include/uapi/linux/bpf.h       | 13 +++++++++
> >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> >  scripts/bpf_helpers_doc.py     |  2 ++
> >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> >  4 files changed, 76 insertions(+)
> >
> > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > index eb5e0c38eb2c..a356ea1357bf 100644
> > --- a/include/uapi/linux/bpf.h
> > +++ b/include/uapi/linux/bpf.h
> > @@ -3389,6 +3389,18 @@ union bpf_attr {
> >   *             A non-negative value equal to or less than *size* on success,
> >   *             or a negative error in case of failure.
> >   *
> > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> 
> nit: probably would be good to do `const struct path *` here, even if
> we don't do const-ification properly in all helpers.

ok

> 
> > + *     Description
> > + *             Return full path for given 'struct path' object, which
> > + *             needs to be the kernel BTF 'path' object. The path is
> > + *             returned in buffer provided 'buf' of size 'sz' and
> 
> typo: in the provided buffer 'buf' of size ... ?

ugh, sure

> 
> > + *             is zero terminated.
> > + *
> > + *     Return
> > + *             On success, the strictly positive length of the string,
> > + *             including the trailing NUL character. On error, a negative
> > + *             value.
> > + *
> >   */
> >  #define __BPF_FUNC_MAPPER(FN)          \
> >         FN(unspec),                     \
> > @@ -3533,6 +3545,7 @@ union bpf_attr {
> >         FN(skc_to_tcp_request_sock),    \
> >         FN(skc_to_udp6_sock),           \
> >         FN(get_task_stack),             \
> > +       FN(d_path),                     \
> >         /* */
> >
> >  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
> > index cb91ef902cc4..02a76e246545 100644
> > --- a/kernel/trace/bpf_trace.c
> > +++ b/kernel/trace/bpf_trace.c
> > @@ -1098,6 +1098,52 @@ static const struct bpf_func_proto bpf_send_signal_thread_proto = {
> >         .arg1_type      = ARG_ANYTHING,
> >  };
> >
> > +BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz)
> > +{
> > +       int len;
> > +       char *p;
> > +
> > +       if (!sz)
> > +               return -ENAMETOOLONG;
> 
> if we are modeling this after bpf_probe_read_str(), sz == 0 returns
> success and just does nothing. I don't think anyone will ever handle
> or expect this error. I'd just return 0.

ook

thanks,
jirka
Jiri Olsa Aug. 5, 2020, 9:01 p.m. UTC | #5
On Wed, Aug 05, 2020 at 07:58:54PM +0200, Jiri Olsa wrote:
> On Tue, Aug 04, 2020 at 11:35:53PM -0700, Andrii Nakryiko wrote:
> > On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
> > >
> > > Adding d_path helper function that returns full path for
> > > given 'struct path' object, which needs to be the kernel
> > > BTF 'path' object. The path is returned in buffer provided
> > > 'buf' of size 'sz' and is zero terminated.
> > >
> > >   bpf_d_path(&file->f_path, buf, size);
> > >
> > > The helper calls directly d_path function, so there's only
> > > limited set of function it can be called from. Adding just
> > > very modest set for the start.
> > >
> > > Updating also bpf.h tools uapi header and adding 'path' to
> > > bpf_helpers_doc.py script.
> > >
> > > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > > ---
> > >  include/uapi/linux/bpf.h       | 13 +++++++++
> > >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> > >  scripts/bpf_helpers_doc.py     |  2 ++
> > >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> > >  4 files changed, 76 insertions(+)
> > >
> > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > index eb5e0c38eb2c..a356ea1357bf 100644
> > > --- a/include/uapi/linux/bpf.h
> > > +++ b/include/uapi/linux/bpf.h
> > > @@ -3389,6 +3389,18 @@ union bpf_attr {
> > >   *             A non-negative value equal to or less than *size* on success,
> > >   *             or a negative error in case of failure.
> > >   *
> > > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> > 
> > nit: probably would be good to do `const struct path *` here, even if
> > we don't do const-ification properly in all helpers.

hum, for this I need to update scripts/bpf_helpers_doc.py and it looks
like it's not ready for const struct yet:

  CLNG-LLC [test_maps] get_cgroup_id_kern.o
In file included from progs/test_lwt_ip_encap.c:7:
In file included from /home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helpers.h:11:
/home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helper_defs.h:32:1: warning: 'const' ignored on this declaration [-Wmissing-declarations]
const struct path;
^

would it be ok as a follow up change? I'll need to check
on bpf_helpers_doc.py script first

jirka
Andrii Nakryiko Aug. 5, 2020, 9:09 p.m. UTC | #6
On Wed, Aug 5, 2020 at 2:01 PM Jiri Olsa <jolsa@redhat.com> wrote:
>
> On Wed, Aug 05, 2020 at 07:58:54PM +0200, Jiri Olsa wrote:
> > On Tue, Aug 04, 2020 at 11:35:53PM -0700, Andrii Nakryiko wrote:
> > > On Sat, Aug 1, 2020 at 10:04 AM Jiri Olsa <jolsa@kernel.org> wrote:
> > > >
> > > > Adding d_path helper function that returns full path for
> > > > given 'struct path' object, which needs to be the kernel
> > > > BTF 'path' object. The path is returned in buffer provided
> > > > 'buf' of size 'sz' and is zero terminated.
> > > >
> > > >   bpf_d_path(&file->f_path, buf, size);
> > > >
> > > > The helper calls directly d_path function, so there's only
> > > > limited set of function it can be called from. Adding just
> > > > very modest set for the start.
> > > >
> > > > Updating also bpf.h tools uapi header and adding 'path' to
> > > > bpf_helpers_doc.py script.
> > > >
> > > > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > > > ---
> > > >  include/uapi/linux/bpf.h       | 13 +++++++++
> > > >  kernel/trace/bpf_trace.c       | 48 ++++++++++++++++++++++++++++++++++
> > > >  scripts/bpf_helpers_doc.py     |  2 ++
> > > >  tools/include/uapi/linux/bpf.h | 13 +++++++++
> > > >  4 files changed, 76 insertions(+)
> > > >
> > > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> > > > index eb5e0c38eb2c..a356ea1357bf 100644
> > > > --- a/include/uapi/linux/bpf.h
> > > > +++ b/include/uapi/linux/bpf.h
> > > > @@ -3389,6 +3389,18 @@ union bpf_attr {
> > > >   *             A non-negative value equal to or less than *size* on success,
> > > >   *             or a negative error in case of failure.
> > > >   *
> > > > + * int bpf_d_path(struct path *path, char *buf, u32 sz)
> > >
> > > nit: probably would be good to do `const struct path *` here, even if
> > > we don't do const-ification properly in all helpers.
>
> hum, for this I need to update scripts/bpf_helpers_doc.py and it looks
> like it's not ready for const struct yet:
>
>   CLNG-LLC [test_maps] get_cgroup_id_kern.o
> In file included from progs/test_lwt_ip_encap.c:7:
> In file included from /home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helpers.h:11:
> /home/jolsa/linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_helper_defs.h:32:1: warning: 'const' ignored on this declaration [-Wmissing-declarations]
> const struct path;
> ^
>
> would it be ok as a follow up change? I'll need to check
> on bpf_helpers_doc.py script first

yeah, no big deal

>
> jirka
>
KP Singh Aug. 7, 2020, 12:31 a.m. UTC | #7
On Sat, Aug 1, 2020 at 7:04 PM Jiri Olsa <jolsa@kernel.org> wrote:
>
> Adding d_path helper function that returns full path for

[...]

> +}
> +
> +BTF_SET_START(btf_allowlist_d_path)
> +BTF_ID(func, vfs_truncate)
> +BTF_ID(func, vfs_fallocate)
> +BTF_ID(func, dentry_open)
> +BTF_ID(func, vfs_getattr)
> +BTF_ID(func, filp_close)
> +BTF_SET_END(btf_allowlist_d_path)
> +

> +static bool bpf_d_path_allowed(const struct bpf_prog *prog)
> +{
> +       return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
> +}

Can we allow it for LSM programs too?

- KP

> +
> +BTF_ID_LIST(bpf_d_path_btf_ids)
> +BTF_ID(struct, path)
> +

[...]

>
>  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> --
> 2.25.4
>
Jiri Olsa Aug. 7, 2020, 8:35 a.m. UTC | #8
On Fri, Aug 07, 2020 at 02:31:52AM +0200, KP Singh wrote:
> On Sat, Aug 1, 2020 at 7:04 PM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding d_path helper function that returns full path for
> 
> [...]
> 
> > +}
> > +
> > +BTF_SET_START(btf_allowlist_d_path)
> > +BTF_ID(func, vfs_truncate)
> > +BTF_ID(func, vfs_fallocate)
> > +BTF_ID(func, dentry_open)
> > +BTF_ID(func, vfs_getattr)
> > +BTF_ID(func, filp_close)
> > +BTF_SET_END(btf_allowlist_d_path)
> > +
> 
> > +static bool bpf_d_path_allowed(const struct bpf_prog *prog)
> > +{
> > +       return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
> > +}
> 
> Can we allow it for LSM programs too?

yes, that's why I used struct bpf_prog as argument, so we could reach the
program type.. but I was hoping we could do that in follow up patchset,
because I assume there might be still some discussion about that?

I plan to post new version today

jirka

> 
> - KP
> 
> > +
> > +BTF_ID_LIST(bpf_d_path_btf_ids)
> > +BTF_ID(struct, path)
> > +
> 
> [...]
> 
> >
> >  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > --
> > 2.25.4
> >
>
KP Singh Aug. 7, 2020, 9:42 a.m. UTC | #9
On Fri, Aug 7, 2020 at 10:35 AM Jiri Olsa <jolsa@redhat.com> wrote:
>
> On Fri, Aug 07, 2020 at 02:31:52AM +0200, KP Singh wrote:
> > On Sat, Aug 1, 2020 at 7:04 PM Jiri Olsa <jolsa@kernel.org> wrote:
> > >
> > > Adding d_path helper function that returns full path for
> >
> > [...]
> >
> > > +}
> > > +
> > > +BTF_SET_START(btf_allowlist_d_path)
> > > +BTF_ID(func, vfs_truncate)
> > > +BTF_ID(func, vfs_fallocate)
> > > +BTF_ID(func, dentry_open)
> > > +BTF_ID(func, vfs_getattr)
> > > +BTF_ID(func, filp_close)
> > > +BTF_SET_END(btf_allowlist_d_path)
> > > +
> >
> > > +static bool bpf_d_path_allowed(const struct bpf_prog *prog)
> > > +{
> > > +       return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
> > > +}
> >
> > Can we allow it for LSM programs too?
>
> yes, that's why I used struct bpf_prog as argument, so we could reach the

Thanks for adding the bpf_prog argument.

> program type.. but I was hoping we could do that in follow up patchset,

Sure. We can do it in a follow-up patch.

- KP

> because I assume there might be still some discussion about that?
>
> I plan to post new version today
>
> jirka
>
> >
> > - KP
> >
> > > +
> > > +BTF_ID_LIST(bpf_d_path_btf_ids)
> > > +BTF_ID(struct, path)
> > > +
> >
> > [...]
> >
> > >
> > >  /* integer value in 'imm' field of BPF_CALL instruction selects which helper
> > > --
> > > 2.25.4
> > >
> >
>
diff mbox series

Patch

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index eb5e0c38eb2c..a356ea1357bf 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3389,6 +3389,18 @@  union bpf_attr {
  *		A non-negative value equal to or less than *size* on success,
  *		or a negative error in case of failure.
  *
+ * int bpf_d_path(struct path *path, char *buf, u32 sz)
+ *	Description
+ *		Return full path for given 'struct path' object, which
+ *		needs to be the kernel BTF 'path' object. The path is
+ *		returned in buffer provided 'buf' of size 'sz' and
+ *		is zero terminated.
+ *
+ *	Return
+ *		On success, the strictly positive length of the string,
+ *		including the trailing NUL character. On error, a negative
+ *		value.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -3533,6 +3545,7 @@  union bpf_attr {
 	FN(skc_to_tcp_request_sock),	\
 	FN(skc_to_udp6_sock),		\
 	FN(get_task_stack),		\
+	FN(d_path),			\
 	/* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index cb91ef902cc4..02a76e246545 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1098,6 +1098,52 @@  static const struct bpf_func_proto bpf_send_signal_thread_proto = {
 	.arg1_type	= ARG_ANYTHING,
 };
 
+BPF_CALL_3(bpf_d_path, struct path *, path, char *, buf, u32, sz)
+{
+	int len;
+	char *p;
+
+	if (!sz)
+		return -ENAMETOOLONG;
+
+	p = d_path(path, buf, sz);
+	if (IS_ERR(p)) {
+		len = PTR_ERR(p);
+	} else {
+		len = buf + sz - p;
+		memmove(buf, p, len);
+	}
+
+	return len;
+}
+
+BTF_SET_START(btf_allowlist_d_path)
+BTF_ID(func, vfs_truncate)
+BTF_ID(func, vfs_fallocate)
+BTF_ID(func, dentry_open)
+BTF_ID(func, vfs_getattr)
+BTF_ID(func, filp_close)
+BTF_SET_END(btf_allowlist_d_path)
+
+static bool bpf_d_path_allowed(const struct bpf_prog *prog)
+{
+	return btf_id_set_contains(&btf_allowlist_d_path, prog->aux->attach_btf_id);
+}
+
+BTF_ID_LIST(bpf_d_path_btf_ids)
+BTF_ID(struct, path)
+
+static const struct bpf_func_proto bpf_d_path_proto = {
+	.func		= bpf_d_path,
+	.gpl_only	= false,
+	.ret_type	= RET_INTEGER,
+	.arg1_type	= ARG_PTR_TO_BTF_ID,
+	.arg2_type	= ARG_PTR_TO_MEM,
+	.arg3_type	= ARG_CONST_SIZE_OR_ZERO,
+	.btf_id		= bpf_d_path_btf_ids,
+	.allowed	= bpf_d_path_allowed,
+};
+
 const struct bpf_func_proto *
 bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
@@ -1579,6 +1625,8 @@  tracing_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 		return prog->expected_attach_type == BPF_TRACE_ITER ?
 		       &bpf_seq_write_proto :
 		       NULL;
+	case BPF_FUNC_d_path:
+		return &bpf_d_path_proto;
 	default:
 		return raw_tp_prog_func_proto(func_id, prog);
 	}
diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py
index 5bfa448b4704..08388173973f 100755
--- a/scripts/bpf_helpers_doc.py
+++ b/scripts/bpf_helpers_doc.py
@@ -432,6 +432,7 @@  class PrinterHelpers(Printer):
             'struct __sk_buff',
             'struct sk_msg_md',
             'struct xdp_md',
+            'struct path',
     ]
     known_types = {
             '...',
@@ -472,6 +473,7 @@  class PrinterHelpers(Printer):
             'struct tcp_request_sock',
             'struct udp6_sock',
             'struct task_struct',
+            'struct path',
     }
     mapped_types = {
             'u8': '__u8',
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index eb5e0c38eb2c..a356ea1357bf 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3389,6 +3389,18 @@  union bpf_attr {
  *		A non-negative value equal to or less than *size* on success,
  *		or a negative error in case of failure.
  *
+ * int bpf_d_path(struct path *path, char *buf, u32 sz)
+ *	Description
+ *		Return full path for given 'struct path' object, which
+ *		needs to be the kernel BTF 'path' object. The path is
+ *		returned in buffer provided 'buf' of size 'sz' and
+ *		is zero terminated.
+ *
+ *	Return
+ *		On success, the strictly positive length of the string,
+ *		including the trailing NUL character. On error, a negative
+ *		value.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)		\
 	FN(unspec),			\
@@ -3533,6 +3545,7 @@  union bpf_attr {
 	FN(skc_to_tcp_request_sock),	\
 	FN(skc_to_udp6_sock),		\
 	FN(get_task_stack),		\
+	FN(d_path),			\
 	/* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper