Add support for BPF hooks for io_uring setsockopts command. This implementation follows a similar approach to what __sys_setsockopt() does, but, operates only on kernel memory instead of user memory (which is also possible, but not preferred since the kernel memory is already available) Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx> --- io_uring/uring_cmd.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c index 3693e5779229..b7b27e4dbddd 100644 --- a/io_uring/uring_cmd.c +++ b/io_uring/uring_cmd.c @@ -205,23 +205,42 @@ static inline int io_uring_cmd_setsockopt(struct socket *sock, { void __user *optval = u64_to_user_ptr(READ_ONCE(cmd->sqe->optval)); int optname = READ_ONCE(cmd->sqe->optname); + sockptr_t optval_s = USER_SOCKPTR(optval); int optlen = READ_ONCE(cmd->sqe->optlen); int level = READ_ONCE(cmd->sqe->level); + char *kernel_optval = NULL; int err; err = security_socket_setsockopt(sock, level, optname); if (err) return err; + if (!in_compat_syscall()) { + err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, + &optname, + USER_SOCKPTR(optval), + &optlen, + &kernel_optval); + if (err < 0) + return err; + if (err > 0) + return 0; + + /* Replace optval by the one returned by BPF */ + if (kernel_optval) + optval_s = KERNEL_SOCKPTR(kernel_optval); + } + if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock)) err = sock_setsockopt(sock, level, optname, - USER_SOCKPTR(optval), optlen); + optval_s, optlen); else if (unlikely(!sock->ops->setsockopt)) err = -EOPNOTSUPP; else err = sock->ops->setsockopt(sock, level, optname, - USER_SOCKPTR(koptval), optlen); + optval_s, optlen); + kfree(kernel_optval); return err; } -- 2.34.1