Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Add sockptr support for getsockopt

The whole network stack uses sockptr, and while it doesn't move to
something more modern, let's use sockptr in getsockptr 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-2-leitao@debian.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Breno Leitao and committed by
Jens Axboe
a615f67e 6ce4a93d

+17 -13
+3 -2
include/linux/bpf-cgroup.h
··· 139 139 int __cgroup_bpf_run_filter_setsockopt(struct sock *sock, int *level, 140 140 int *optname, char __user *optval, 141 141 int *optlen, char **kernel_optval); 142 + 142 143 int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, 143 - int optname, char __user *optval, 144 - int __user *optlen, int max_optlen, 144 + int optname, sockptr_t optval, 145 + sockptr_t optlen, int max_optlen, 145 146 int retval); 146 147 147 148 int __cgroup_bpf_run_filter_getsockopt_kern(struct sock *sk, int level,
+11 -9
kernel/bpf/cgroup.c
··· 1875 1875 } 1876 1876 1877 1877 int __cgroup_bpf_run_filter_getsockopt(struct sock *sk, int level, 1878 - int optname, char __user *optval, 1879 - int __user *optlen, int max_optlen, 1878 + int optname, sockptr_t optval, 1879 + sockptr_t optlen, int max_optlen, 1880 1880 int retval) 1881 1881 { 1882 1882 struct cgroup *cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data); ··· 1903 1903 * one that kernel returned as well to let 1904 1904 * BPF programs inspect the value. 1905 1905 */ 1906 - 1907 - if (get_user(ctx.optlen, optlen)) { 1906 + if (copy_from_sockptr(&ctx.optlen, optlen, 1907 + sizeof(ctx.optlen))) { 1908 1908 ret = -EFAULT; 1909 1909 goto out; 1910 1910 } ··· 1915 1915 } 1916 1916 orig_optlen = ctx.optlen; 1917 1917 1918 - if (copy_from_user(ctx.optval, optval, 1919 - min(ctx.optlen, max_optlen)) != 0) { 1918 + if (copy_from_sockptr(ctx.optval, optval, 1919 + min(ctx.optlen, max_optlen))) { 1920 1920 ret = -EFAULT; 1921 1921 goto out; 1922 1922 } ··· 1930 1930 if (ret < 0) 1931 1931 goto out; 1932 1932 1933 - if (optval && (ctx.optlen > max_optlen || ctx.optlen < 0)) { 1933 + if (!sockptr_is_null(optval) && 1934 + (ctx.optlen > max_optlen || ctx.optlen < 0)) { 1934 1935 if (orig_optlen > PAGE_SIZE && ctx.optlen >= 0) { 1935 1936 pr_info_once("bpf getsockopt: ignoring program buffer with optlen=%d (max_optlen=%d)\n", 1936 1937 ctx.optlen, max_optlen); ··· 1943 1942 } 1944 1943 1945 1944 if (ctx.optlen != 0) { 1946 - if (optval && copy_to_user(optval, ctx.optval, ctx.optlen)) { 1945 + if (!sockptr_is_null(optval) && 1946 + copy_to_sockptr(optval, ctx.optval, ctx.optlen)) { 1947 1947 ret = -EFAULT; 1948 1948 goto out; 1949 1949 } 1950 - if (put_user(ctx.optlen, optlen)) { 1950 + if (copy_to_sockptr(optlen, &ctx.optlen, sizeof(ctx.optlen))) { 1951 1951 ret = -EFAULT; 1952 1952 goto out; 1953 1953 }
+3 -2
net/socket.c
··· 2356 2356 2357 2357 if (!in_compat_syscall()) 2358 2358 err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname, 2359 - optval, optlen, max_optlen, 2360 - err); 2359 + USER_SOCKPTR(optval), 2360 + USER_SOCKPTR(optlen), 2361 + max_optlen, err); 2361 2362 out_put: 2362 2363 fput_light(sock->file, fput_needed); 2363 2364 return err;