2023-08-08 19:54:06

by Breno Leitao

[permalink] [raw]
Subject: [PATCH v2 7/8] io_uring/cmd: BPF hook for getsockopt cmd

Add BPF hooks support for getsockopts io_uring command. So, bpf cgroups
programs can run when SOCKET_URING_OP_GETSOCKOPT command is called.

This implementation follows a similar approach to what
__sys_getsockopt() does, but, using USER_SOCKPTR() for optval instead of
kernel pointer.

Signed-off-by: Breno Leitao <[email protected]>
---
io_uring/uring_cmd.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
index dbba005a7290..3693e5779229 100644
--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -5,6 +5,8 @@
#include <linux/io_uring.h>
#include <linux/security.h>
#include <linux/nospec.h>
+#include <linux/compat.h>
+#include <linux/bpf-cgroup.h>

#include <uapi/linux/io_uring.h>
#include <uapi/asm-generic/ioctls.h>
@@ -179,17 +181,23 @@ static inline int io_uring_cmd_getsockopt(struct socket *sock,
if (err)
return err;

- if (level == SOL_SOCKET) {
+ err = -EOPNOTSUPP;
+ if (level == SOL_SOCKET)
err = sk_getsockopt(sock->sk, level, optname,
USER_SOCKPTR(optval),
KERNEL_SOCKPTR(&optlen));
- if (err)
- return err;

+ if (!in_compat_syscall())
+ err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level,
+ optname,
+ USER_SOCKPTR(optval),
+ KERNEL_SOCKPTR(&optlen),
+ optlen, err);
+
+ if (!err)
return optlen;
- }

- return -EOPNOTSUPP;
+ return err;
}

static inline int io_uring_cmd_setsockopt(struct socket *sock,
--
2.34.1



2023-08-09 06:06:02

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] io_uring/cmd: BPF hook for getsockopt cmd

Hi Breno,

kernel test robot noticed the following build errors:

[auto build test ERROR on next-20230808]
[cannot apply to bpf-next/master bpf/master net/main net-next/main linus/master horms-ipvs/master v6.5-rc5 v6.5-rc4 v6.5-rc3 v6.5-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Breno-Leitao/net-expose-sock_use_custom_sol_socket/20230809-011901
base: next-20230808
patch link: https://lore.kernel.org/r/20230808134049.1407498-8-leitao%40debian.org
patch subject: [PATCH v2 7/8] io_uring/cmd: BPF hook for getsockopt cmd
config: x86_64-randconfig-r012-20230808 (https://download.01.org/0day-ci/archive/20230809/[email protected]/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230809/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

In file included from include/linux/export.h:5,
from include/linux/linkage.h:7,
from include/linux/kernel.h:17,
from io_uring/uring_cmd.c:2:
io_uring/uring_cmd.c: In function 'io_uring_cmd_getsockopt':
>> include/linux/bpf-cgroup.h:393:41: error: 'tcp_bpf_bypass_getsockopt' undeclared (first use in this function)
393 | tcp_bpf_bypass_getsockopt, \
| ^~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler.h:76:45: note: in definition of macro 'likely'
76 | # define likely(x) __builtin_expect(!!(x), 1)
| ^
include/linux/indirect_call_wrapper.h:66:42: note: in expansion of macro 'INDIRECT_CALL_1'
66 | #define INDIRECT_CALL_INET_1(f, f1, ...) INDIRECT_CALL_1(f, f1, __VA_ARGS__)
| ^~~~~~~~~~~~~~~
include/linux/bpf-cgroup.h:392:22: note: in expansion of macro 'INDIRECT_CALL_INET_1'
392 | !INDIRECT_CALL_INET_1((sock)->sk_prot->bpf_bypass_getsockopt, \
| ^~~~~~~~~~~~~~~~~~~~
io_uring/uring_cmd.c:191:23: note: in expansion of macro 'BPF_CGROUP_RUN_PROG_GETSOCKOPT'
191 | err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/bpf-cgroup.h:393:41: note: each undeclared identifier is reported only once for each function it appears in
393 | tcp_bpf_bypass_getsockopt, \
| ^~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler.h:76:45: note: in definition of macro 'likely'
76 | # define likely(x) __builtin_expect(!!(x), 1)
| ^
include/linux/indirect_call_wrapper.h:66:42: note: in expansion of macro 'INDIRECT_CALL_1'
66 | #define INDIRECT_CALL_INET_1(f, f1, ...) INDIRECT_CALL_1(f, f1, __VA_ARGS__)
| ^~~~~~~~~~~~~~~
include/linux/bpf-cgroup.h:392:22: note: in expansion of macro 'INDIRECT_CALL_INET_1'
392 | !INDIRECT_CALL_INET_1((sock)->sk_prot->bpf_bypass_getsockopt, \
| ^~~~~~~~~~~~~~~~~~~~
io_uring/uring_cmd.c:191:23: note: in expansion of macro 'BPF_CGROUP_RUN_PROG_GETSOCKOPT'
191 | err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from include/net/sock.h:62,
from include/linux/bpf-cgroup.h:11,
from io_uring/uring_cmd.c:9:
>> include/linux/bpf-cgroup.h:393:41: error: implicit declaration of function 'tcp_bpf_bypass_getsockopt' [-Werror=implicit-function-declaration]
393 | tcp_bpf_bypass_getsockopt, \
| ^~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/indirect_call_wrapper.h:19:35: note: in definition of macro 'INDIRECT_CALL_1'
19 | likely(f == f1) ? f1(__VA_ARGS__) : f(__VA_ARGS__); \
| ^~
include/linux/bpf-cgroup.h:392:22: note: in expansion of macro 'INDIRECT_CALL_INET_1'
392 | !INDIRECT_CALL_INET_1((sock)->sk_prot->bpf_bypass_getsockopt, \
| ^~~~~~~~~~~~~~~~~~~~
io_uring/uring_cmd.c:191:23: note: in expansion of macro 'BPF_CGROUP_RUN_PROG_GETSOCKOPT'
191 | err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_uring/uring_cmd.c: In function 'io_uring_cmd_setsockopt':
io_uring/uring_cmd.c:223:58: error: 'koptval' undeclared (first use in this function); did you mean 'optval'?
223 | USER_SOCKPTR(koptval), optlen);
| ^~~~~~~
| optval
cc1: some warnings being treated as errors


vim +/tcp_bpf_bypass_getsockopt +393 include/linux/bpf-cgroup.h

0d01da6afc5402 Stanislav Fomichev 2019-06-27 384
0d01da6afc5402 Stanislav Fomichev 2019-06-27 385 #define BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock, level, optname, optval, optlen, \
0d01da6afc5402 Stanislav Fomichev 2019-06-27 386 max_optlen, retval) \
0d01da6afc5402 Stanislav Fomichev 2019-06-27 387 ({ \
0d01da6afc5402 Stanislav Fomichev 2019-06-27 388 int __ret = retval; \
46531a30364bd4 Pavel Begunkov 2022-01-27 389 if (cgroup_bpf_enabled(CGROUP_GETSOCKOPT) && \
46531a30364bd4 Pavel Begunkov 2022-01-27 390 cgroup_bpf_sock_enabled(sock, CGROUP_GETSOCKOPT)) \
9cacf81f816111 Stanislav Fomichev 2021-01-15 391 if (!(sock)->sk_prot->bpf_bypass_getsockopt || \
9cacf81f816111 Stanislav Fomichev 2021-01-15 392 !INDIRECT_CALL_INET_1((sock)->sk_prot->bpf_bypass_getsockopt, \
9cacf81f816111 Stanislav Fomichev 2021-01-15 @393 tcp_bpf_bypass_getsockopt, \
9cacf81f816111 Stanislav Fomichev 2021-01-15 394 level, optname)) \
9cacf81f816111 Stanislav Fomichev 2021-01-15 395 __ret = __cgroup_bpf_run_filter_getsockopt( \
9cacf81f816111 Stanislav Fomichev 2021-01-15 396 sock, level, optname, optval, optlen, \
9cacf81f816111 Stanislav Fomichev 2021-01-15 397 max_optlen, retval); \
9cacf81f816111 Stanislav Fomichev 2021-01-15 398 __ret; \
9cacf81f816111 Stanislav Fomichev 2021-01-15 399 })
9cacf81f816111 Stanislav Fomichev 2021-01-15 400

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-08-09 16:59:47

by Gabriel Krisman Bertazi

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] io_uring/cmd: BPF hook for getsockopt cmd

Breno Leitao <[email protected]> writes:

> Add BPF hooks support for getsockopts io_uring command. So, bpf cgroups
> programs can run when SOCKET_URING_OP_GETSOCKOPT command is called.
>
> This implementation follows a similar approach to what
> __sys_getsockopt() does, but, using USER_SOCKPTR() for optval instead of
> kernel pointer.
>
> Signed-off-by: Breno Leitao <[email protected]>
> ---
> io_uring/uring_cmd.c | 18 +++++++++++++-----
> 1 file changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
> index dbba005a7290..3693e5779229 100644
> --- a/io_uring/uring_cmd.c
> +++ b/io_uring/uring_cmd.c
> @@ -5,6 +5,8 @@
> #include <linux/io_uring.h>
> #include <linux/security.h>
> #include <linux/nospec.h>
> +#include <linux/compat.h>
> +#include <linux/bpf-cgroup.h>
>
> #include <uapi/linux/io_uring.h>
> #include <uapi/asm-generic/ioctls.h>
> @@ -179,17 +181,23 @@ static inline int io_uring_cmd_getsockopt(struct socket *sock,
> if (err)
> return err;
>
> - if (level == SOL_SOCKET) {
> + err = -EOPNOTSUPP;
> + if (level == SOL_SOCKET)
> err = sk_getsockopt(sock->sk, level, optname,
> USER_SOCKPTR(optval),
> KERNEL_SOCKPTR(&optlen));
> - if (err)
> - return err;
>
> + if (!in_compat_syscall())
> + err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level,
> + optname,
> + USER_SOCKPTR(optval),
> + KERNEL_SOCKPTR(&optlen),
> + optlen, err);

I'm not sure if it makes sense to use in_compat_syscall() here. Can't
this be invoked in a ring with ctx->compat set, but from outside a
compat syscall context (i.e. from sqpoll or even a !compat
io_uring_enter syscall)? I suspect you might need to check ctx->compact
instead, but I'm not sure. Did you consider that?

> +
> + if (!err)
> return optlen;
> - }
>
> - return -EOPNOTSUPP;
> + return err;
> }
>
> static inline int io_uring_cmd_setsockopt(struct socket *sock,

--
Gabriel Krisman Bertazi

2023-08-10 08:57:38

by Breno Leitao

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] io_uring/cmd: BPF hook for getsockopt cmd

Hello Gabriel,

On Wed, Aug 09, 2023 at 12:46:27PM -0400, Gabriel Krisman Bertazi wrote:
> Breno Leitao <[email protected]> writes:
>
> > Add BPF hooks support for getsockopts io_uring command. So, bpf cgroups
> > programs can run when SOCKET_URING_OP_GETSOCKOPT command is called.
> >
> > This implementation follows a similar approach to what
> > __sys_getsockopt() does, but, using USER_SOCKPTR() for optval instead of
> > kernel pointer.
> >
> > Signed-off-by: Breno Leitao <[email protected]>
> > ---
> > io_uring/uring_cmd.c | 18 +++++++++++++-----
> > 1 file changed, 13 insertions(+), 5 deletions(-)
> >
> > diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
> > index dbba005a7290..3693e5779229 100644
> > --- a/io_uring/uring_cmd.c
> > +++ b/io_uring/uring_cmd.c
> > @@ -5,6 +5,8 @@
> > #include <linux/io_uring.h>
> > #include <linux/security.h>
> > #include <linux/nospec.h>
> > +#include <linux/compat.h>
> > +#include <linux/bpf-cgroup.h>
> >
> > #include <uapi/linux/io_uring.h>
> > #include <uapi/asm-generic/ioctls.h>
> > @@ -179,17 +181,23 @@ static inline int io_uring_cmd_getsockopt(struct socket *sock,
> > if (err)
> > return err;
> >
> > - if (level == SOL_SOCKET) {
> > + err = -EOPNOTSUPP;
> > + if (level == SOL_SOCKET)
> > err = sk_getsockopt(sock->sk, level, optname,
> > USER_SOCKPTR(optval),
> > KERNEL_SOCKPTR(&optlen));
> > - if (err)
> > - return err;
> >
> > + if (!in_compat_syscall())
> > + err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level,
> > + optname,
> > + USER_SOCKPTR(optval),
> > + KERNEL_SOCKPTR(&optlen),
> > + optlen, err);
>
> I'm not sure if it makes sense to use in_compat_syscall() here. Can't
> this be invoked in a ring with ctx->compat set, but from outside a
> compat syscall context (i.e. from sqpoll or even a !compat
> io_uring_enter syscall)? I suspect you might need to check ctx->compact
> instead, but I'm not sure. Did you consider that?

I think that checking ctx->compat seems to be the right thing to do. I
will update.