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.

net/socket: Break down __sys_getsockopt

Split __sys_getsockopt() into two functions by removing the core
logic into a sub-function (do_sock_getsockopt()). This will avoid
code duplication when doing the same operation in other callers, for
instance.

do_sock_getsockopt() will be called by io_uring getsockopt() command
operation in the following patch.

The same was done for the setsockopt pair.

Suggested-by: Martin KaFai Lau <martin.lau@linux.dev>
Signed-off-by: Breno Leitao <leitao@debian.org>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Acked-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20231016134750.1381153-5-leitao@debian.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Breno Leitao and committed by
Jens Axboe
0b05b0cd 1406245c

+44 -34
+1 -1
include/linux/bpf-cgroup.h
··· 378 378 ({ \ 379 379 int __ret = 0; \ 380 380 if (cgroup_bpf_enabled(CGROUP_GETSOCKOPT)) \ 381 - get_user(__ret, optlen); \ 381 + copy_from_sockptr(&__ret, optlen, sizeof(int)); \ 382 382 __ret; \ 383 383 }) 384 384
+2 -2
include/net/sock.h
··· 1869 1869 sockptr_t optval, unsigned int optlen); 1870 1870 int do_sock_setsockopt(struct socket *sock, bool compat, int level, 1871 1871 int optname, sockptr_t optval, int optlen); 1872 + int do_sock_getsockopt(struct socket *sock, bool compat, int level, 1873 + int optname, sockptr_t optval, sockptr_t optlen); 1872 1874 1873 1875 int sk_getsockopt(struct sock *sk, int level, int optname, 1874 1876 sockptr_t optval, sockptr_t optlen); 1875 - int sock_getsockopt(struct socket *sock, int level, int op, 1876 - char __user *optval, int __user *optlen); 1877 1877 int sock_gettstamp(struct socket *sock, void __user *userstamp, 1878 1878 bool timeval, bool time32); 1879 1879 struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
-8
net/core/sock.c
··· 2010 2010 return 0; 2011 2011 } 2012 2012 2013 - int sock_getsockopt(struct socket *sock, int level, int optname, 2014 - char __user *optval, int __user *optlen) 2015 - { 2016 - return sk_getsockopt(sock->sk, level, optname, 2017 - USER_SOCKPTR(optval), 2018 - USER_SOCKPTR(optlen)); 2019 - } 2020 - 2021 2013 /* 2022 2014 * Initialize an sk_lock. 2023 2015 *
+41 -23
net/socket.c
··· 2333 2333 INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level, 2334 2334 int optname)); 2335 2335 2336 + int do_sock_getsockopt(struct socket *sock, bool compat, int level, 2337 + int optname, sockptr_t optval, sockptr_t optlen) 2338 + { 2339 + int max_optlen __maybe_unused; 2340 + const struct proto_ops *ops; 2341 + int err; 2342 + 2343 + err = security_socket_getsockopt(sock, level, optname); 2344 + if (err) 2345 + return err; 2346 + 2347 + if (!compat) 2348 + max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); 2349 + 2350 + ops = READ_ONCE(sock->ops); 2351 + if (level == SOL_SOCKET) { 2352 + err = sk_getsockopt(sock->sk, level, optname, optval, optlen); 2353 + } else if (unlikely(!ops->getsockopt)) { 2354 + err = -EOPNOTSUPP; 2355 + } else { 2356 + if (WARN_ONCE(optval.is_kernel || optlen.is_kernel, 2357 + "Invalid argument type")) 2358 + return -EOPNOTSUPP; 2359 + 2360 + err = ops->getsockopt(sock, level, optname, optval.user, 2361 + optlen.user); 2362 + } 2363 + 2364 + if (!compat) 2365 + err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname, 2366 + optval, optlen, max_optlen, 2367 + err); 2368 + 2369 + return err; 2370 + } 2371 + EXPORT_SYMBOL(do_sock_getsockopt); 2372 + 2336 2373 /* 2337 2374 * Get a socket option. Because we don't know the option lengths we have 2338 2375 * to pass a user mode parameter for the protocols to sort out. ··· 2377 2340 int __sys_getsockopt(int fd, int level, int optname, char __user *optval, 2378 2341 int __user *optlen) 2379 2342 { 2380 - int max_optlen __maybe_unused; 2381 - const struct proto_ops *ops; 2382 2343 int err, fput_needed; 2383 2344 struct socket *sock; 2345 + bool compat; 2384 2346 2385 2347 sock = sockfd_lookup_light(fd, &err, &fput_needed); 2386 2348 if (!sock) 2387 2349 return err; 2388 2350 2389 - err = security_socket_getsockopt(sock, level, optname); 2390 - if (err) 2391 - goto out_put; 2351 + compat = in_compat_syscall(); 2352 + err = do_sock_getsockopt(sock, compat, level, optname, 2353 + USER_SOCKPTR(optval), USER_SOCKPTR(optlen)); 2392 2354 2393 - if (!in_compat_syscall()) 2394 - max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); 2395 - 2396 - ops = READ_ONCE(sock->ops); 2397 - if (level == SOL_SOCKET) 2398 - err = sock_getsockopt(sock, level, optname, optval, optlen); 2399 - else if (unlikely(!ops->getsockopt)) 2400 - err = -EOPNOTSUPP; 2401 - else 2402 - err = ops->getsockopt(sock, level, optname, optval, 2403 - optlen); 2404 - 2405 - if (!in_compat_syscall()) 2406 - err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname, 2407 - USER_SOCKPTR(optval), 2408 - USER_SOCKPTR(optlen), 2409 - max_optlen, err); 2410 - out_put: 2411 2355 fput_light(sock->file, fput_needed); 2412 2356 return err; 2413 2357 }