On Wed, Oct 21, 2026 at 12:58:36PM -0700, Allison Henderson wrote: > With CONFIG_SYSCTL=n, register_net_sysctl() and register_net_sysctl_sz() > are inline stubs that return NULL. rds_sysctl_init(), > rds_ib_sysctl_init() and rds_tcp_init_net() all treat that NULL as > -ENOMEM, so RDS refuses to initialize at all even though every tunable > has a sane compiled-in default. > > When RDS is built in, that is worse than a missing feature: the failed > rds_init() destroys rds_wq, but the rds_rdma initcall still runs, and > when rds_ib_sysctl_init() fails the same way, the error path in > rds_ib_init() flushes the already freed workqueue: > > BUG: KASAN: slab-use-after-free in touch_wq_lockdep_map > ... > __flush_workqueue > rds_ib_init > rds_rdma_init > ... > Allocated by task 1: > alloc_workqueue_noprof > rds_threads_init > rds_init > ... > Freed by task 0: > kfree > rcu_do_batch > > Only treat the NULL return as a failure when sysctl support is actually > compiled in. The exit paths need no change: unregister_net_sysctl_table() > is an empty stub with CONFIG_SYSCTL=n and already tolerates a NULL header > otherwise. > > The underlying problem of built-in transports initializing after > rds_init() has failed is independent of sysctl and is addressed > separately. > > Reported-by: kernel test robot > Closes: https://lore.kernel.org/oe-lkp/202610190310.9737b2e3-lkp@intel.com > Fixes: 3e5048495c85 ("RDS: sysctls") > Fixes: e6babe4cc4ce ("RDS/IB: Stats and sysctls") > Fixes: c6a58ffed536 ("RDS: TCP: Add sysctl tunables for sndbuf/rcvbuf on rds-tcp socket") > Suggested-by: Joel Granados > Assisted-by: LLM > Signed-off-by: Allison Henderson > --- > net/rds/ib_sysctl.c | 2 +- > net/rds/sysctl.c | 2 +- > net/rds/tcp.c | 2 +- > 3 files changed, 3 insertions(+), 3 deletions(-) > > diff --git a/net/rds/ib_sysctl.c b/net/rds/ib_sysctl.c > index 2af678e71e3c..bc97a3eecad6 100644 > --- a/net/rds/ib_sysctl.c > +++ b/net/rds/ib_sysctl.c > @@ -114,7 +114,7 @@ void rds_ib_sysctl_exit(void) > int rds_ib_sysctl_init(void) > { > rds_ib_sysctl_hdr = register_net_sysctl(&init_net, "net/rds/ib", rds_ib_sysctl_table); > - if (!rds_ib_sysctl_hdr) > + if (!rds_ib_sysctl_hdr && IS_ENABLED(CONFIG_SYSCTL)) > return -ENOMEM; > return 0; > } > diff --git a/net/rds/sysctl.c b/net/rds/sysctl.c > index 025f518a4349..968d6279bbd3 100644 > --- a/net/rds/sysctl.c > +++ b/net/rds/sysctl.c > @@ -103,7 +103,7 @@ int rds_sysctl_init(void) > > rds_sysctl_reg_table = > register_net_sysctl(&init_net, "net/rds", rds_sysctl_rds_table); > - if (!rds_sysctl_reg_table) > + if (!rds_sysctl_reg_table && IS_ENABLED(CONFIG_SYSCTL)) > return -ENOMEM; > return 0; > } > diff --git a/net/rds/tcp.c b/net/rds/tcp.c > index 774a71f88d37..34815b4f658b 100644 > --- a/net/rds/tcp.c > +++ b/net/rds/tcp.c > @@ -637,7 +637,7 @@ static __net_init int rds_tcp_init_net(struct net *net) > tbl[RDS_TCP_RCVBUF].data = &rtn->rcvbuf_size; > rtn->rds_tcp_sysctl = register_net_sysctl_sz(net, "net/rds/tcp", tbl, > ARRAY_SIZE(rds_tcp_sysctl_table)); > - if (!rtn->rds_tcp_sysctl) { > + if (!rtn->rds_tcp_sysctl && IS_ENABLED(CONFIG_SYSCTL)) { > pr_warn("could not register sysctl\n"); > err = -ENOMEM; > goto fail; > -- > 2.50.1 > This LGTM Reviewed-by: Joel Granados