mirror of
https://github.com/torvalds/linux.git
synced 2026-10-28 17:55:02 +01:00
rds_info_getsockopt() reads a callback from rds_info_funcs and invokes it
without protecting the callback's lifetime. Transport modules register
functions stored in this array. For example, rds_tcp.ko registers
rds_tcp_tc_info() for RDS_INFO_TCP_SOCKETS.
This permits the following interleaving:
CPU0 CPU1
rds_info_getsockopt()
func = rds_tcp_tc_info
rmmod rds_tcp
rds_tcp_exit()
rds_info_deregister_func()
rds_info_funcs[offset] = NULL
free rds_tcp module text
func()
The reader can therefore branch to an address in unloaded module text.
Protect callback invocation with SRCU. Enter the SRCU read-side critical
section before loading the callback and leave it only after the callback
returns. Clear the callback with WRITE_ONCE() and call
synchronize_srcu() before deregistration returns, preventing module unload
from freeing its text while an old reader is still executing it. SRCU is
required because callbacks such as RDS_INFO_COUNTERS can sleep.
Keep the callback array unannotated and use READ_ONCE() and WRITE_ONCE()
for concurrent slot access so sparse does not have to apply __rcu through
the function-pointer typedef. Replace the two callback-slot BUG_ON()
checks with WARN_ON_ONCE() and return without changing the slot on
mismatch.
Link: https://lore.kernel.org/netdev/20260720184955.3008978-1-nicoyip.dev@gmail.com/
Suggested-by: Allison Henderson <achender@kernel.org>
Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Allison Henderson <achender@kernel.org>
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Link: https://patch.msgid.link/20260801054234.3535077-1-nicoyip.dev@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||
|---|---|---|
| .. | ||
| af_rds.c | ||
| bind.c | ||
| cong.c | ||
| connection.c | ||
| ib_cm.c | ||
| ib_frmr.c | ||
| ib_mr.h | ||
| ib_rdma.c | ||
| ib_recv.c | ||
| ib_ring.c | ||
| ib_send.c | ||
| ib_stats.c | ||
| ib_sysctl.c | ||
| ib.c | ||
| ib.h | ||
| info.c | ||
| info.h | ||
| Kconfig | ||
| loop.c | ||
| loop.h | ||
| Makefile | ||
| message.c | ||
| page.c | ||
| rdma_transport.c | ||
| rdma_transport.h | ||
| rdma.c | ||
| rds_single_path.h | ||
| rds.h | ||
| recv.c | ||
| send.c | ||
| stats.c | ||
| sysctl.c | ||
| tcp_connect.c | ||
| tcp_listen.c | ||
| tcp_recv.c | ||
| tcp_send.c | ||
| tcp_stats.c | ||
| tcp.c | ||
| tcp.h | ||
| threads.c | ||
| transport.c | ||