bpf: Add sockptr support for setsockopt
authorBreno Leitao <leitao@debian.org>
Mon, 16 Oct 2023 13:47:40 +0000 (06:47 -0700)
committerJens Axboe <axboe@kernel.dk>
Thu, 19 Oct 2023 20:05:37 +0000 (14:05 -0600)
The whole network stack uses sockptr, and while it doesn't move to
something more modern, let's use sockptr in setsockptr BPF hooks, so, it
could be used by other callers.

The main motivation for this change is to use it in the io_uring
{g,s}etsockopt(), which will use a userspace pointer for *optval, but, a
kernel value for optlen.

Link: https://lore.kernel.org/all/ZSArfLaaGcfd8LH8@gmail.com/
Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20231016134750.1381153-3-leitao@debian.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/bpf-cgroup.h
kernel/bpf/cgroup.c
net/socket.c

index f5b4fb6ed8c67e75510215db88ff12015c416455..cecfe8c99f280acc0d3caa7e2714126e45d9bde5 100644 (file)
@@ -137,7 +137,7 @@ int __cgroup_bpf_run_filter_sysctl(struct ctl_table_header *head,
                                   enum cgroup_bpf_attach_type atype);
 
 int __cgroup_bpf_run_filter_setsockopt(struct sock *sock, int *level,
-                                      int *optname, char __user *optval,
+                                      int *optname, sockptr_t optval,
                                       int *optlen, char **kernel_optval);
 
 int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level,
index ebc8c58f7e46589010080d99118074ae1704802f..f0dedd4f7f2ea9b598ec61be383c731c2842dd37 100644 (file)
@@ -1785,7 +1785,7 @@ static bool sockopt_buf_allocated(struct bpf_sockopt_kern *ctx,
 }
 
 int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
-                                      int *optname, char __user *optval,
+                                      int *optname, sockptr_t optval,
                                       int *optlen, char **kernel_optval)
 {
        struct cgroup *cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
@@ -1808,7 +1808,8 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
 
        ctx.optlen = *optlen;
 
-       if (copy_from_user(ctx.optval, optval, min(*optlen, max_optlen)) != 0) {
+       if (copy_from_sockptr(ctx.optval, optval,
+                             min(*optlen, max_optlen))) {
                ret = -EFAULT;
                goto out;
        }
index 82cd6890a4f0b36bd59236108bd92126725b63db..9a43f6e850c72e28951203855e429e8bd6201ca7 100644 (file)
@@ -2288,7 +2288,7 @@ int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
 
        if (!in_compat_syscall())
                err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
-                                                    user_optval, &optlen,
+                                                    optval, &optlen,
                                                     &kernel_optval);
        if (err < 0)
                goto out_put;