Message ID | 20230911103407.1393149-3-leitao@debian.org (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | io_uring: Initial support for {s,g}etsockopt commands | expand |
On Mon, 2023-09-11 at 03:34 -0700, Breno Leitao wrote: > Split __sys_getsockopt() into two functions by removing the core > logic into a sub-function (do_sock_getsockopt()). This will avoid > code duplication when executing the same operation in other callers, for > instance. > > do_sock_getsockopt() will be called by io_uring getsockopt() command > operation in the following patch. > > Suggested-by: Martin KaFai Lau <martin.lau@linux.dev> > Signed-off-by: Breno Leitao <leitao@debian.org> > --- > include/net/sock.h | 3 +++ > net/socket.c | 51 ++++++++++++++++++++++++++++------------------ > 2 files changed, 34 insertions(+), 20 deletions(-) > > diff --git a/include/net/sock.h b/include/net/sock.h > index aa8fb54ad0af..fbd568a43d28 100644 > --- a/include/net/sock.h > +++ b/include/net/sock.h > @@ -1863,6 +1863,9 @@ int sock_setsockopt(struct socket *sock, int level, int op, > sockptr_t optval, unsigned int optlen); > int do_sock_setsockopt(struct socket *sock, bool compat, int level, > int optname, char __user *user_optval, int optlen); > +int do_sock_getsockopt(struct socket *sock, bool compat, int level, > + int optname, char __user *user_optval, > + int __user *user_optlen); > > int sk_getsockopt(struct sock *sk, int level, int optname, > sockptr_t optval, sockptr_t optlen); > diff --git a/net/socket.c b/net/socket.c > index 360332e098d4..3ec779a56f79 100644 > --- a/net/socket.c > +++ b/net/socket.c > @@ -2333,28 +2333,17 @@ SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, > INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level, > int optname)); > > -/* > - * Get a socket option. Because we don't know the option lengths we have > - * to pass a user mode parameter for the protocols to sort out. > - */ > -int __sys_getsockopt(int fd, int level, int optname, char __user *optval, > - int __user *optlen) > +int do_sock_getsockopt(struct socket *sock, bool compat, int level, > + int optname, char __user *optval, > + int __user *optlen) > { > int max_optlen __maybe_unused; > const struct proto_ops *ops; > - int err, fput_needed; > - struct socket *sock; > - > - sock = sockfd_lookup_light(fd, &err, &fput_needed); > - if (!sock) > - return err; > + int err; > > err = security_socket_getsockopt(sock, level, optname); > if (err) > - goto out_put; > - > - if (!in_compat_syscall()) > - max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); > + return err; > > ops = READ_ONCE(sock->ops); > if (level == SOL_SOCKET) > @@ -2362,14 +2351,36 @@ int __sys_getsockopt(int fd, int level, int optname, char __user *optval, > else if (unlikely(!ops->getsockopt)) > err = -EOPNOTSUPP; > else > - err = ops->getsockopt(sock, level, optname, optval, > - optlen); > + err = ops->getsockopt(sock, level, optname, optval, optlen); > > - if (!in_compat_syscall()) > + if (!compat) { > + max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); > err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname, > optval, optlen, max_optlen, > err); > -out_put: > + } > + > + return err; > +} > +EXPORT_SYMBOL(do_sock_getsockopt); > + > +/* Get a socket option. Because we don't know the option lengths we have > + * to pass a user mode parameter for the protocols to sort out. > + */ > +int __sys_getsockopt(int fd, int level, int optname, char __user *optval, > + int __user *optlen) > +{ > + int err, fput_needed; > + bool compat = in_compat_syscall(); > + struct socket *sock; Please respect the reverse x-mas tree order, thanks! Paolo
diff --git a/include/net/sock.h b/include/net/sock.h index aa8fb54ad0af..fbd568a43d28 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1863,6 +1863,9 @@ int sock_setsockopt(struct socket *sock, int level, int op, sockptr_t optval, unsigned int optlen); int do_sock_setsockopt(struct socket *sock, bool compat, int level, int optname, char __user *user_optval, int optlen); +int do_sock_getsockopt(struct socket *sock, bool compat, int level, + int optname, char __user *user_optval, + int __user *user_optlen); int sk_getsockopt(struct sock *sk, int level, int optname, sockptr_t optval, sockptr_t optlen); diff --git a/net/socket.c b/net/socket.c index 360332e098d4..3ec779a56f79 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2333,28 +2333,17 @@ SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level, int optname)); -/* - * Get a socket option. Because we don't know the option lengths we have - * to pass a user mode parameter for the protocols to sort out. - */ -int __sys_getsockopt(int fd, int level, int optname, char __user *optval, - int __user *optlen) +int do_sock_getsockopt(struct socket *sock, bool compat, int level, + int optname, char __user *optval, + int __user *optlen) { int max_optlen __maybe_unused; const struct proto_ops *ops; - int err, fput_needed; - struct socket *sock; - - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (!sock) - return err; + int err; err = security_socket_getsockopt(sock, level, optname); if (err) - goto out_put; - - if (!in_compat_syscall()) - max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); + return err; ops = READ_ONCE(sock->ops); if (level == SOL_SOCKET) @@ -2362,14 +2351,36 @@ int __sys_getsockopt(int fd, int level, int optname, char __user *optval, else if (unlikely(!ops->getsockopt)) err = -EOPNOTSUPP; else - err = ops->getsockopt(sock, level, optname, optval, - optlen); + err = ops->getsockopt(sock, level, optname, optval, optlen); - if (!in_compat_syscall()) + if (!compat) { + max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname, optval, optlen, max_optlen, err); -out_put: + } + + return err; +} +EXPORT_SYMBOL(do_sock_getsockopt); + +/* Get a socket option. Because we don't know the option lengths we have + * to pass a user mode parameter for the protocols to sort out. + */ +int __sys_getsockopt(int fd, int level, int optname, char __user *optval, + int __user *optlen) +{ + int err, fput_needed; + bool compat = in_compat_syscall(); + struct socket *sock; + + sock = sockfd_lookup_light(fd, &err, &fput_needed); + if (!sock) + return err; + + err = do_sock_getsockopt(sock, compat, level, optname, optval, + optlen); + fput_light(sock->file, fput_needed); return err; }
Split __sys_getsockopt() into two functions by removing the core logic into a sub-function (do_sock_getsockopt()). This will avoid code duplication when executing the same operation in other callers, for instance. do_sock_getsockopt() will be called by io_uring getsockopt() command operation in the following patch. Suggested-by: Martin KaFai Lau <martin.lau@linux.dev> Signed-off-by: Breno Leitao <leitao@debian.org> --- include/net/sock.h | 3 +++ net/socket.c | 51 ++++++++++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 20 deletions(-)