diff mbox series

[v2,7/8] io_uring/cmd: BPF hook for getsockopt cmd

Message ID 20230808134049.1407498-8-leitao@debian.org (mailing list archive)
State Superseded
Headers show
Series io_uring: Initial support for {s,g}etsockopt commands | expand

Checks

Context Check Description
netdev/tree_selection success Guessing tree name failed - patch did not apply
bpf/vmtest-bpf-PR success PR summary
bpf/vmtest-bpf-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-VM_Test-2 success Logs for build for aarch64 with gcc
bpf/vmtest-bpf-VM_Test-3 pending Logs for build for s390x with gcc
bpf/vmtest-bpf-VM_Test-4 success Logs for build for x86_64 with gcc
bpf/vmtest-bpf-VM_Test-5 success Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-VM_Test-6 success Logs for set-matrix

Commit Message

Breno Leitao Aug. 8, 2023, 1:40 p.m. UTC
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 <leitao@debian.org>
---
 io_uring/uring_cmd.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

Comments

kernel test robot Aug. 9, 2023, 4:17 a.m. UTC | #1
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/202308091149.ltz0y4QZ-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230809/202308091149.ltz0y4QZ-lkp@intel.com/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 <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202308091149.ltz0y4QZ-lkp@intel.com/

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
Gabriel Krisman Bertazi Aug. 9, 2023, 4:46 p.m. UTC | #2
Breno Leitao <leitao@debian.org> 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 <leitao@debian.org>
> ---
>  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,
Breno Leitao Aug. 10, 2023, 8:26 a.m. UTC | #3
Hello Gabriel,

On Wed, Aug 09, 2023 at 12:46:27PM -0400, Gabriel Krisman Bertazi wrote:
> Breno Leitao <leitao@debian.org> 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 <leitao@debian.org>
> > ---
> >  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.
diff mbox series

Patch

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,