diff options
| author | Tze-nan Wu <[email protected]> | 2024-08-30 08:25:17 +0000 |
|---|---|---|
| committer | Jakub Kicinski <[email protected]> | 2024-09-03 19:06:24 +0000 |
| commit | 33f339a1ba54e56bba57ee9a77c71e385ab4825c (patch) | |
| tree | 66713861c1b04e6459e0e652925f112e4bfafeb5 /net/socket.c | |
| parent | net: dqs: Do not use extern for unused dql_group (diff) | |
| download | kernel-33f339a1ba54e56bba57ee9a77c71e385ab4825c.tar.gz kernel-33f339a1ba54e56bba57ee9a77c71e385ab4825c.zip | |
bpf, net: Fix a potential race in do_sock_getsockopt()
There's a potential race when `cgroup_bpf_enabled(CGROUP_GETSOCKOPT)` is
false during the execution of `BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN`, but
becomes true when `BPF_CGROUP_RUN_PROG_GETSOCKOPT` is called.
This inconsistency can lead to `BPF_CGROUP_RUN_PROG_GETSOCKOPT` receiving
an "-EFAULT" from `__cgroup_bpf_run_filter_getsockopt(max_optlen=0)`.
Scenario shown as below:
`process A` `process B`
----------- ------------
BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN
enable CGROUP_GETSOCKOPT
BPF_CGROUP_RUN_PROG_GETSOCKOPT (-EFAULT)
To resolve this, remove the `BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN` macro and
directly uses `copy_from_sockptr` to ensure that `max_optlen` is always
set before `BPF_CGROUP_RUN_PROG_GETSOCKOPT` is invoked.
Fixes: 0d01da6afc54 ("bpf: implement getsockopt and setsockopt hooks")
Co-developed-by: Yanghui Li <[email protected]>
Signed-off-by: Yanghui Li <[email protected]>
Co-developed-by: Cheng-Jui Wang <[email protected]>
Signed-off-by: Cheng-Jui Wang <[email protected]>
Signed-off-by: Tze-nan Wu <[email protected]>
Acked-by: Stanislav Fomichev <[email protected]>
Acked-by: Alexei Starovoitov <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
Diffstat (limited to 'net/socket.c')
| -rw-r--r-- | net/socket.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/net/socket.c b/net/socket.c index fcbdd5bc47ac..0a2bd22ec105 100644 --- a/net/socket.c +++ b/net/socket.c @@ -2362,7 +2362,7 @@ INDIRECT_CALLABLE_DECLARE(bool tcp_bpf_bypass_getsockopt(int level, int do_sock_getsockopt(struct socket *sock, bool compat, int level, int optname, sockptr_t optval, sockptr_t optlen) { - int max_optlen __maybe_unused; + int max_optlen __maybe_unused = 0; const struct proto_ops *ops; int err; @@ -2371,7 +2371,7 @@ int do_sock_getsockopt(struct socket *sock, bool compat, int level, return err; if (!compat) - max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen); + copy_from_sockptr(&max_optlen, optlen, sizeof(int)); ops = READ_ONCE(sock->ops); if (level == SOL_SOCKET) { |
