From nobody Mon Aug 24 01:40:34 2026 Received: from mta0.migadu.com (out-71.mta0.migadu.com [91.218.175.71]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 71E502931D5 for ; Tue, 18 Aug 2026 09:48:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.71 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046521; cv=none; b=Sv4g+P1jQTG1KQmRck21pwSfwGv7t6p6aqDx6lmgaYPd9MCp6uJreNGIhDWBy3v0Xo9PL2C1zblipsNvApsQ5YuQiCSFZAZka5/QcL5JVuochGZgLS6L1XBoxHRwtiqdHnbm6aAx85ogqvXTIr8efl4PkDIir6EbcwrBLvTnniY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046521; c=relaxed/simple; bh=BJFT3fymzW56qJMpkj/E8kk8/P/XLkJtEru++M0qohI=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cO5Ku1wByHBb8lGX+EMdvkyNlTKzW4BJXQINTQhz6TqH4MzRvFHliI7kvTTPsKIdqxMgODomMFIC3PZi+eLXFX6H0SWdZoMHZmZmm/9A36HQmYEBGrHJ7MW/zAP7D4YOPpMmTO+9l9T6cRm9JrjWQwwbwpC3qH1WEusUd3XCHrs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=L1eWCcgl; arc=none smtp.client-ip=91.218.175.71 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="L1eWCcgl" X-Envelope-To: mptcp@lists.linux.dev DKIM-Signature: a=rsa-sha256; bh=BJFT3fymzW56qJMpkj/E8kk8/P/XLkJtEru++M0qohI=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787046516; v=1; x=1787651316; b=L1eWCcglYpF+LlblfBeg8x1mQtLb1KIcsydwy2xiKjj54NoZoBMUWpVvNdJfdHzs8xhz6W4O arh64JCAIUx0lZJrXiCk9OxfRmS1iUVDzRYaemvkM8oTkZ9MAvXLGsNy5CEFItFTq/UAzKTLytF idthuoHS7GV0wERyGoHbYZ7Q= X-Envelope-To: mptcp@lists.linux.dev Received: from thinkbook16p.. (223.70.159.239) by smtp.migadu.com with ESMTPS id 263189bb712f6688; Tue, 18 Aug 2026 09:48:36 +0000 X-Migadu-Flow: FLOW_OUT From: Gang Yan To: mptcp@lists.linux.dev Subject: [PATCH mptcp-next v2 1/5] mptcp: sched: change scheduler sysctl atomically Date: Tue, 18 Aug 2026 17:48:21 +0800 Message-ID: <20260818094825.48446-2-gang.yan@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260818094825.48446-1-gang.yan@linux.dev> References: <20260818094825.48446-1-gang.yan@linux.dev> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gang Yan The per-netns scheduler name is stored as an inline char[] buffer and updated via strscpy() from the sysctl handler. A concurrent reader (e.g. mptcp_init_sock() resolving the default scheduler) can observe a half-written name, which is also flagged by KCSAN. READ_ONCE() does not help here as it cannot read a multi-byte string atomically. Following the tcp_congestion_control() model, store a pointer to the immutable struct mptcp_sched_ops instead of the name string: - mptcp_set_scheduler() now looks the ops up and atomically swaps the pernet pointer with xchg(); - mptcp_get_scheduler() copies the ops name out under rcu_read_lock(); - the default ops is assigned in mptcp_pernet_set_defaults(). A pointer store is a single atomic word, so readers always observe a consistent value. Assisted-by: Claude:GLM5.2 Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/626 Co-developed-by: Tao Cui Signed-off-by: Tao Cui Signed-off-by: Gang Yan --- net/mptcp/ctrl.c | 31 ++++++++++++++++++++++--------- net/mptcp/protocol.c | 5 +++-- net/mptcp/protocol.h | 3 ++- net/mptcp/sched.c | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c index 63c5747f0f63..479b31eb3007 100644 --- a/net/mptcp/ctrl.c +++ b/net/mptcp/ctrl.c @@ -39,7 +39,7 @@ struct mptcp_pernet { u8 allow_join_initial_addr_port; u8 pm_type; u8 add_addr_v6_port_drop_ts; - char scheduler[MPTCP_SCHED_NAME_MAX]; + struct mptcp_sched_ops __rcu *scheduler; char path_manager[MPTCP_PM_NAME_MAX]; }; =20 @@ -90,9 +90,14 @@ const char *mptcp_get_path_manager(const struct net *net) return mptcp_get_pernet(net)->path_manager; } =20 -const char *mptcp_get_scheduler(const struct net *net) +void mptcp_get_scheduler(const struct net *net, char *name) { - return mptcp_get_pernet(net)->scheduler; + struct mptcp_sched_ops *sched; + + rcu_read_lock(); + sched =3D rcu_dereference(mptcp_get_pernet(net)->scheduler); + strscpy(name, sched ? sched->name : "default", MPTCP_SCHED_NAME_MAX); + rcu_read_unlock(); } =20 unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net) @@ -112,13 +117,15 @@ static void mptcp_pernet_set_defaults(struct mptcp_pe= rnet *pernet) pernet->allow_join_initial_addr_port =3D 1; pernet->stale_loss_cnt =3D 4; pernet->pm_type =3D MPTCP_PM_TYPE_KERNEL; - strscpy(pernet->scheduler, "default", sizeof(pernet->scheduler)); + + RCU_INIT_POINTER(pernet->scheduler, &mptcp_sched_default); + strscpy(pernet->path_manager, "kernel", sizeof(pernet->path_manager)); pernet->add_addr_v6_port_drop_ts =3D 1; } =20 #ifdef CONFIG_SYSCTL -static int mptcp_set_scheduler(char *scheduler, const char *name) +static int mptcp_set_scheduler(struct mptcp_pernet *pernet, const char *na= me) { struct mptcp_sched_ops *sched; int ret =3D 0; @@ -126,7 +133,7 @@ static int mptcp_set_scheduler(char *scheduler, const c= har *name) rcu_read_lock(); sched =3D mptcp_sched_find(name); if (sched) - strscpy(scheduler, name, MPTCP_SCHED_NAME_MAX); + xchg(&pernet->scheduler, sched); else ret =3D -ENOENT; rcu_read_unlock(); @@ -137,7 +144,10 @@ static int mptcp_set_scheduler(char *scheduler, const = char *name) static int proc_scheduler(const struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) { - char (*scheduler)[MPTCP_SCHED_NAME_MAX] =3D ctl->data; + struct mptcp_pernet *pernet =3D container_of(ctl->data, + struct mptcp_pernet, + scheduler); + struct mptcp_sched_ops *sched; char val[MPTCP_SCHED_NAME_MAX]; struct ctl_table tbl =3D { .data =3D val, @@ -145,11 +155,14 @@ static int proc_scheduler(const struct ctl_table *ctl= , int write, }; int ret; =20 - strscpy(val, *scheduler, MPTCP_SCHED_NAME_MAX); + rcu_read_lock(); + sched =3D rcu_dereference(pernet->scheduler); + strscpy(val, sched ? sched->name : "default", MPTCP_SCHED_NAME_MAX); + rcu_read_unlock(); =20 ret =3D proc_dostring(&tbl, write, buffer, lenp, ppos); if (write && ret =3D=3D 0) - ret =3D mptcp_set_scheduler(*scheduler, val); + ret =3D mptcp_set_scheduler(pernet, val); =20 return ret; } diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index f879b1061f2d..9d84dd803802 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -3260,6 +3260,7 @@ static void mptcp_ca_reset(struct sock *sk) static int mptcp_init_sock(struct sock *sk) { struct net *net =3D sock_net(sk); + char sched_name[MPTCP_SCHED_NAME_MAX]; int ret; =20 __mptcp_init_sock(sk); @@ -3271,8 +3272,8 @@ static int mptcp_init_sock(struct sock *sk) return -ENOMEM; =20 rcu_read_lock(); - ret =3D mptcp_init_sched(mptcp_sk(sk), - mptcp_sched_find(mptcp_get_scheduler(net))); + mptcp_get_scheduler(net, sched_name); + ret =3D mptcp_init_sched(mptcp_sk(sk), mptcp_sched_find(sched_name)); rcu_read_unlock(); if (ret) return ret; diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 7e168e450fb0..af79b3450ab7 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -803,7 +803,7 @@ unsigned int mptcp_stale_loss_cnt(const struct net *net= ); unsigned int mptcp_close_timeout(const struct sock *sk); int mptcp_get_pm_type(const struct net *net); const char *mptcp_get_path_manager(const struct net *net); -const char *mptcp_get_scheduler(const struct net *net); +void mptcp_get_scheduler(const struct net *net, char *name); unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net); =20 void mptcp_active_disable(struct sock *sk); @@ -1155,6 +1155,7 @@ int mptcp_pm_remove_addr(struct mptcp_sock *msk, cons= t struct mptcp_rm_list *rm_ =20 /* the default path manager, used in mptcp_pm_unregister */ extern struct mptcp_pm_ops mptcp_pm_kernel; +extern struct mptcp_sched_ops mptcp_sched_default; =20 struct mptcp_pm_ops *mptcp_pm_find(const char *name); int mptcp_pm_register(struct mptcp_pm_ops *pm_ops); diff --git a/net/mptcp/sched.c b/net/mptcp/sched.c index 1e59072d478c..0d13ee46ffdf 100644 --- a/net/mptcp/sched.c +++ b/net/mptcp/sched.c @@ -40,7 +40,7 @@ static int mptcp_sched_default_get_retrans(struct mptcp_s= ock *msk) return 0; } =20 -static struct mptcp_sched_ops mptcp_sched_default =3D { +struct mptcp_sched_ops mptcp_sched_default =3D { .get_send =3D mptcp_sched_default_get_send, .get_retrans =3D mptcp_sched_default_get_retrans, .name =3D "default", --=20 2.43.0 From nobody Mon Aug 24 01:40:34 2026 Received: from mta0.migadu.com (out-72.mta0.migadu.com [91.218.175.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A89FF43F0B8 for ; Tue, 18 Aug 2026 09:48:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046522; cv=none; b=DeizKZzfe2YD9gaqKA/fScTrvk0Hb78RveX2hu83hJHGTtEN068MbbScgvFLGLFR0+WTNQ4pVBESF93cDxjrf4a4OnZp7H8bkfZUuH34my/4AXqH1AV83KX0QeWIM0Noy60sIarpzzhEHVAfXgHF9vCo3DUCicCUM6nsfuuC740= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046522; c=relaxed/simple; bh=AmanxY6H7ETiONFDj3xk4NmGJs6kcBNWQt76OaUOEKk=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OETcntg4xKcF60S+rIV5hl1TPkIh057S6Qww3MIXtpJJ0ORz6EY2GRjurjkTawTSz4TbpMqtWV4x9T19KC22bWcMRTHZ0kTTFHJRB75kLhtfhb8YPjQ26vOthD4rjbwsvZaUonglJnqouyUHYsthL1hyVWZZsuLEZVB6GdLU6a0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=ffR22wXX; arc=none smtp.client-ip=91.218.175.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="ffR22wXX" X-Envelope-To: mptcp@lists.linux.dev DKIM-Signature: a=rsa-sha256; bh=AmanxY6H7ETiONFDj3xk4NmGJs6kcBNWQt76OaUOEKk=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787046518; v=1; x=1787651318; b=ffR22wXXzLKIIObEP4oS3oTZHZqi1Fy6mV3fvI7yGZPZMdQV3FZxut+dKs88w4pph/959qLt aNoqE/gQ7vka99fDIM7AgAvXwFzXdL+YorfgjRMUgJbF1EvDIeFHeuoUmIO/6JB6+U8hxoBa7c+ mhfXQ6nuK5zrYQ80PI2JYNjI= X-Envelope-To: mptcp@lists.linux.dev Received: from thinkbook16p.. (223.70.159.239) by smtp.migadu.com with ESMTPS id e13d26de5bcb86be; Tue, 18 Aug 2026 09:48:38 +0000 X-Migadu-Flow: FLOW_OUT From: Gang Yan To: mptcp@lists.linux.dev Subject: [PATCH mptcp-next v2 2/5] mptcp: pm: change path_manager sysctl atomically Date: Tue, 18 Aug 2026 17:48:22 +0800 Message-ID: <20260818094825.48446-3-gang.yan@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260818094825.48446-1-gang.yan@linux.dev> References: <20260818094825.48446-1-gang.yan@linux.dev> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gang Yan The per-netns path manager name is stored as an inline char[] buffer and updated via strscpy() from the sysctl handler; a concurrent reader can observe a half-written name (and KCSAN flags the race), which READ_ONCE() cannot fix for a multi-byte string. Following the tcp_congestion_control() model (and the scheduler change in the previous patch), store a pointer to the immutable struct mptcp_pm_ops instead of the name string: - mptcp_set_path_manager() looks the ops up and atomically swaps the pernet pointer with xchg(); - mptcp_get_path_manager() copies the ops name out under rcu_read_lock(); - the default ops is assigned in mptcp_pernet_set_defaults(). Assisted-by: Claude:GLM5.2 Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/626 Co-developed-by: Tao Cui Signed-off-by: Tao Cui Signed-off-by: Gang Yan --- net/mptcp/ctrl.c | 28 ++++++++++++++++++---------- net/mptcp/pm.c | 3 ++- net/mptcp/protocol.h | 3 +-- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c index 479b31eb3007..c0481b09c1a1 100644 --- a/net/mptcp/ctrl.c +++ b/net/mptcp/ctrl.c @@ -40,7 +40,7 @@ struct mptcp_pernet { u8 pm_type; u8 add_addr_v6_port_drop_ts; struct mptcp_sched_ops __rcu *scheduler; - char path_manager[MPTCP_PM_NAME_MAX]; + struct mptcp_pm_ops __rcu *path_manager; }; =20 static struct mptcp_pernet *mptcp_get_pernet(const struct net *net) @@ -85,9 +85,14 @@ int mptcp_get_pm_type(const struct net *net) return mptcp_get_pernet(net)->pm_type; } =20 -const char *mptcp_get_path_manager(const struct net *net) +void mptcp_get_path_manager(const struct net *net, char *name) { - return mptcp_get_pernet(net)->path_manager; + struct mptcp_pm_ops *pm_ops; + + rcu_read_lock(); + pm_ops =3D rcu_dereference(mptcp_get_pernet(net)->path_manager); + strscpy(name, pm_ops ? pm_ops->name : "kernel", MPTCP_PM_NAME_MAX); + rcu_read_unlock(); } =20 void mptcp_get_scheduler(const struct net *net, char *name) @@ -119,8 +124,8 @@ static void mptcp_pernet_set_defaults(struct mptcp_pern= et *pernet) pernet->pm_type =3D MPTCP_PM_TYPE_KERNEL; =20 RCU_INIT_POINTER(pernet->scheduler, &mptcp_sched_default); + RCU_INIT_POINTER(pernet->path_manager, &mptcp_pm_kernel); =20 - strscpy(pernet->path_manager, "kernel", sizeof(pernet->path_manager)); pernet->add_addr_v6_port_drop_ts =3D 1; } =20 @@ -201,7 +206,7 @@ static int proc_blackhole_detect_timeout(const struct c= tl_table *table, return ret; } =20 -static int mptcp_set_path_manager(char *path_manager, const char *name) +static int mptcp_set_path_manager(struct mptcp_pernet *pernet, const char = *name) { struct mptcp_pm_ops *pm_ops; int ret =3D 0; @@ -209,7 +214,7 @@ static int mptcp_set_path_manager(char *path_manager, c= onst char *name) rcu_read_lock(); pm_ops =3D mptcp_pm_find(name); if (pm_ops) - strscpy(path_manager, name, MPTCP_PM_NAME_MAX); + xchg(&pernet->path_manager, pm_ops); else ret =3D -ENOENT; rcu_read_unlock(); @@ -223,7 +228,7 @@ static int proc_path_manager(const struct ctl_table *ct= l, int write, struct mptcp_pernet *pernet =3D container_of(ctl->data, struct mptcp_pernet, path_manager); - char (*path_manager)[MPTCP_PM_NAME_MAX] =3D ctl->data; + struct mptcp_pm_ops *pm_ops; char pm_name[MPTCP_PM_NAME_MAX]; const struct ctl_table tbl =3D { .data =3D pm_name, @@ -231,11 +236,14 @@ static int proc_path_manager(const struct ctl_table *= ctl, int write, }; int ret; =20 - strscpy(pm_name, *path_manager, MPTCP_PM_NAME_MAX); + rcu_read_lock(); + pm_ops =3D rcu_dereference(pernet->path_manager); + strscpy(pm_name, pm_ops ? pm_ops->name : "kernel", MPTCP_PM_NAME_MAX); + rcu_read_unlock(); =20 ret =3D proc_dostring(&tbl, write, buffer, lenp, ppos); if (write && ret =3D=3D 0) { - ret =3D mptcp_set_path_manager(*path_manager, pm_name); + ret =3D mptcp_set_path_manager(pernet, pm_name); if (ret =3D=3D 0) { u8 pm_type =3D __MPTCP_PM_TYPE_NR; =20 @@ -267,7 +275,7 @@ static int proc_pm_type(const struct ctl_table *ctl, in= t write, pm_name =3D "kernel"; else if (pm_type =3D=3D MPTCP_PM_TYPE_USERSPACE) pm_name =3D "userspace"; - mptcp_set_path_manager(pernet->path_manager, pm_name); + mptcp_set_path_manager(pernet, pm_name); } =20 return ret; diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index ba7c6f80a183..09f99bcd827c 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -1204,7 +1204,7 @@ void mptcp_pm_destroy(struct mptcp_sock *msk) void mptcp_pm_data_reset(struct mptcp_sock *msk) { const struct net *net =3D sock_net((struct sock *)msk); - const char *pm_name =3D mptcp_get_path_manager(net); + char pm_name[MPTCP_PM_NAME_MAX]; u8 pm_type =3D mptcp_get_pm_type(net); struct mptcp_pm_data *pm =3D &msk->pm; =20 @@ -1213,6 +1213,7 @@ void mptcp_pm_data_reset(struct mptcp_sock *msk) pm->rm_list_rx.nr =3D 0; WRITE_ONCE(pm->pm_type, pm_type); =20 + mptcp_get_path_manager(net, pm_name); rcu_read_lock(); mptcp_pm_ops_init(msk, pm_name); rcu_read_unlock(); diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index af79b3450ab7..99f447f2808f 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -802,7 +802,7 @@ int mptcp_allow_join_id0(const struct net *net); unsigned int mptcp_stale_loss_cnt(const struct net *net); unsigned int mptcp_close_timeout(const struct sock *sk); int mptcp_get_pm_type(const struct net *net); -const char *mptcp_get_path_manager(const struct net *net); +void mptcp_get_path_manager(const struct net *net, char *name); void mptcp_get_scheduler(const struct net *net, char *name); unsigned int mptcp_add_addr_v6_port_drop_ts(const struct net *net); =20 @@ -1153,7 +1153,6 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk, bool echo); int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_lis= t *rm_list); =20 -/* the default path manager, used in mptcp_pm_unregister */ extern struct mptcp_pm_ops mptcp_pm_kernel; extern struct mptcp_sched_ops mptcp_sched_default; =20 --=20 2.43.0 From nobody Mon Aug 24 01:40:34 2026 Received: from mta1.migadu.com (out-58.mta1.migadu.com [95.215.58.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F04D44A3F1 for ; Tue, 18 Aug 2026 09:48:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.58 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046527; cv=none; b=NmZBn6Xdw7WR88xiEaRQBwGZt2Lbcb12DuBW6HhMkS+L+cRFZIhXy4Z8JW/I+gT1740QiPkf4luOKT5l9DtgUob5u3OASNpPVS4FmhOjt8Yalp/1AWunu/XTQjy4aQUO48CSYN0mK0ynCgq/mz9UiAkYxqfXeM00uLC/ydEK94U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046527; c=relaxed/simple; bh=05cTNLwMT8/hVXFkto5mbiM22GsL41QZB1BhW/KJ1mI=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PPwyuTnusbF1spqphSIJRBdu861bOMxx3VQo04SvosKbEp6RS9dCjV75ROtDf2MstvRPI7GJ0T5AvxymMOMHQ2t/2bxFmZeS7hQZReaPzNwZUs9yQ1836mPX1N8bdcS1U0ZuJhtZo/cZy6WTDPFCebRbzotJS7KqQ0SC1PymQeI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=QPgjpA21; arc=none smtp.client-ip=95.215.58.58 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="QPgjpA21" X-Envelope-To: mptcp@lists.linux.dev DKIM-Signature: a=rsa-sha256; bh=05cTNLwMT8/hVXFkto5mbiM22GsL41QZB1BhW/KJ1mI=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787046523; v=1; x=1787651323; b=QPgjpA21v0ZpHBgroOpNJpufNUoXk1lwiEOvP9+uNwmtv2oQx3NKT0NA29afUXzpkSb0rOfi 7nexyj6bgI+1f8FDXQ0t5g/seX94eq1195E8Fon83cVoVZcR44LEGNmyAO5/N/Ajkpj7L7USFh8 H9E4Uy6dB89r2r+v53g1+DjA= X-Envelope-To: mptcp@lists.linux.dev Received: from thinkbook16p.. (223.70.159.239) by smtp.migadu.com with ESMTPS id b2c84cbadcce5fdb; Tue, 18 Aug 2026 09:48:43 +0000 X-Migadu-Flow: FLOW_OUT From: Gang Yan To: mptcp@lists.linux.dev Subject: [PATCH mptcp-next v2 3/5] mptcp: use READ_ONCE() over sysctls Date: Tue, 18 Aug 2026 17:48:23 +0800 Message-ID: <20260818094825.48446-4-gang.yan@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260818094825.48446-1-gang.yan@linux.dev> References: <20260818094825.48446-1-gang.yan@linux.dev> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Matthieu Baerts (NGI0)" To avoid KCSAN issues. This patch is in theory for -net, and will need to be split in multiple patches, with different Fixes tags. But I prefer to wait for Eric's patches, as I noticed he already started to modify mptcp_is_enabled: https://lore.kernel.org/CANn89iLdwhhwLyO6zRjWMEY3t9g60ZE8ZhOVx33ucg_uRETb= mQ@mail.gmail.com Still, keeping this patch in this series, not to forget about it. Also write the pm_type field derived from the path manager name with WRITE_ONCE() in proc_path_manager(), to pair with the READ_ONCE() on mptcp_get_pm_type() added by this patch. Reported-by: Eric Dumazet Closes: https://lore.kernel.org/CANn89iL=3Dos-60kDKqMDdyiXuPF5CG=3DeejS0vmt= hwpDGXz_Bp8A@mail.gmail.com Co-developed-by: Tao Cui Signed-off-by: Tao Cui Signed-off-by: Matthieu Baerts (NGI0) --- net/mptcp/ctrl.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c index c0481b09c1a1..733706f06f1b 100644 --- a/net/mptcp/ctrl.c +++ b/net/mptcp/ctrl.c @@ -50,39 +50,39 @@ static struct mptcp_pernet *mptcp_get_pernet(const stru= ct net *net) =20 int mptcp_is_enabled(const struct net *net) { - return mptcp_get_pernet(net)->mptcp_enabled; + return READ_ONCE(mptcp_get_pernet(net)->mptcp_enabled); } =20 unsigned int mptcp_get_add_addr_timeout(const struct net *net) { - return mptcp_get_pernet(net)->add_addr_timeout; + return READ_ONCE(mptcp_get_pernet(net)->add_addr_timeout); } =20 int mptcp_is_checksum_enabled(const struct net *net) { - return mptcp_get_pernet(net)->checksum_enabled; + return READ_ONCE(mptcp_get_pernet(net)->checksum_enabled); } =20 int mptcp_allow_join_id0(const struct net *net) { - return mptcp_get_pernet(net)->allow_join_initial_addr_port; + return READ_ONCE(mptcp_get_pernet(net)->allow_join_initial_addr_port); } =20 unsigned int mptcp_stale_loss_cnt(const struct net *net) { - return mptcp_get_pernet(net)->stale_loss_cnt; + return READ_ONCE(mptcp_get_pernet(net)->stale_loss_cnt); } =20 unsigned int mptcp_close_timeout(const struct sock *sk) { if (sock_flag(sk, SOCK_DEAD)) return TCP_TIMEWAIT_LEN; - return mptcp_get_pernet(sock_net(sk))->close_timeout; + return READ_ONCE(mptcp_get_pernet(sock_net(sk))->close_timeout); } =20 int mptcp_get_pm_type(const struct net *net) { - return mptcp_get_pernet(net)->pm_type; + return READ_ONCE(mptcp_get_pernet(net)->pm_type); } =20 void mptcp_get_path_manager(const struct net *net, char *name) @@ -251,7 +251,7 @@ static int proc_path_manager(const struct ctl_table *ct= l, int write, pm_type =3D MPTCP_PM_TYPE_KERNEL; else if (strncmp(pm_name, "userspace", MPTCP_PM_NAME_MAX) =3D=3D 0) pm_type =3D MPTCP_PM_TYPE_USERSPACE; - pernet->pm_type =3D pm_type; + WRITE_ONCE(pernet->pm_type, pm_type); } } =20 @@ -572,7 +572,7 @@ void mptcp_active_detect_blackhole(struct sock *ssk, bo= ol expired) =20 net =3D sock_net(ssk); timeouts =3D inet_csk(ssk)->icsk_retransmits; - to_max =3D mptcp_get_pernet(net)->syn_retrans_before_tcp_fallback; + to_max =3D READ_ONCE(mptcp_get_pernet(net)->syn_retrans_before_tcp_fallba= ck); =20 if (timeouts =3D=3D to_max || (timeouts < to_max && expired)) { subflow->mpc_drop =3D 1; --=20 2.43.0 From nobody Mon Aug 24 01:40:34 2026 Received: from mta0.migadu.com (out-75.mta0.migadu.com [91.218.175.75]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BAC1A44C513 for ; Tue, 18 Aug 2026 09:48:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.75 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046532; cv=none; b=potldTQ5hsMRfUODEBasal8+LP4zDEaywZi3yujEthYoJko7sZM/qlRTUxpdrDV98VZLYUHSlVLOobiTdjmf6Ys5woVW1s8AWAFN1m9jfutZCAsvA8DB270D8zZRcZkNPl+m5nzKQBN0t+uH+/dHGzBHFoSX6B/bUxTOcnFjYNc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046532; c=relaxed/simple; bh=PCgQov3XvsNDfArAKr+YVccRtPp71eAPEDq75chPIho=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BmHfvIZin2raL3bhbCzJYpuZZT9DmCFOzviL8AX9SiDD+fFibD4ZHBpB7O0Wqj034yvrp/rmpCfg3ETQ9l7gMxz84mlDXK0sToeOtZPpYD/L8TRRh4xaQn8oNqLX7GIsWL0tjI/RD4N/xXKsbcBPMCH3viyKq7O1YjmhmbxYnP4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=kzvlzRdb; arc=none smtp.client-ip=91.218.175.75 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="kzvlzRdb" X-Envelope-To: mptcp@lists.linux.dev DKIM-Signature: a=rsa-sha256; bh=PCgQov3XvsNDfArAKr+YVccRtPp71eAPEDq75chPIho=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787046528; v=1; x=1787651328; b=kzvlzRdbP93jZcBCV6weXZXtuIzHfqoGNc1vxJurj/+b/DPwcDFvMq0ioTxiBldimqfRPB6b NeiwrnjIQIBN5Amfo9sy+bFAzOnzjW9CLHUt722iQ5gzVcWjp6EQvBKVZ4QNt8hH8ASzESfeKnR NeLKH6vPX+RfghWR/fv/Gqk8= X-Envelope-To: mptcp@lists.linux.dev Received: from thinkbook16p.. (223.70.159.239) by smtp.migadu.com with ESMTPS id 49beae16f087b2a2; Tue, 18 Aug 2026 09:48:48 +0000 X-Migadu-Flow: FLOW_OUT From: Gang Yan To: mptcp@lists.linux.dev Subject: [PATCH mptcp-next v2 4/5] Squash to "mptcp: pm: init and release mptcp_pm_ops" Date: Tue, 18 Aug 2026 17:48:24 +0800 Message-ID: <20260818094825.48446-5-gang.yan@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260818094825.48446-1-gang.yan@linux.dev> References: <20260818094825.48446-1-gang.yan@linux.dev> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gang Yan This commit introduces the mptcp_pm_ops lifetime handling on sockets (mptcp_pm_ops_init/release taking a module reference), and would then be the first one whose per-net path managers can be unloaded while a pernet still stores them. Extend the same reference handling to the pernet level: - mptcp_pernet_set_defaults() pins &mptcp_pm_kernel; - mptcp_set_path_manager() takes a reference on the new ops and releases the one held on the ops it replaces; - mptcp_net_exit() releases the last reference. Depends on the sysctl patches earlier in this series. Assisted-by: Claude:GLM5.2 Co-developed-by: Tao Cui Signed-off-by: Tao Cui Signed-off-by: Gang Yan --- net/mptcp/ctrl.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c index 733706f06f1b..32268aa26097 100644 --- a/net/mptcp/ctrl.c +++ b/net/mptcp/ctrl.c @@ -124,7 +124,9 @@ static void mptcp_pernet_set_defaults(struct mptcp_pern= et *pernet) pernet->pm_type =3D MPTCP_PM_TYPE_KERNEL; =20 RCU_INIT_POINTER(pernet->scheduler, &mptcp_sched_default); - RCU_INIT_POINTER(pernet->path_manager, &mptcp_pm_kernel); + + if (bpf_try_module_get(&mptcp_pm_kernel, mptcp_pm_kernel.owner)) + RCU_INIT_POINTER(pernet->path_manager, &mptcp_pm_kernel); =20 pernet->add_addr_v6_port_drop_ts =3D 1; } @@ -208,15 +210,22 @@ static int proc_blackhole_detect_timeout(const struct= ctl_table *table, =20 static int mptcp_set_path_manager(struct mptcp_pernet *pernet, const char = *name) { - struct mptcp_pm_ops *pm_ops; + struct mptcp_pm_ops *pm_ops, *prev; int ret =3D 0; =20 rcu_read_lock(); pm_ops =3D mptcp_pm_find(name); - if (pm_ops) - xchg(&pernet->path_manager, pm_ops); - else + if (pm_ops) { + if (bpf_try_module_get(pm_ops, pm_ops->owner)) { + prev =3D xchg(&pernet->path_manager, pm_ops); + if (prev) + bpf_module_put(prev, prev->owner); + } else { + ret =3D -EBUSY; + } + } else { ret =3D -ENOENT; + } rcu_read_unlock(); =20 return ret; @@ -594,8 +603,13 @@ static int __net_init mptcp_net_init(struct net *net) static void __net_exit mptcp_net_exit(struct net *net) { struct mptcp_pernet *pernet =3D mptcp_get_pernet(net); + struct mptcp_pm_ops *pm; =20 mptcp_pernet_del_table(pernet); + + pm =3D rcu_dereference_protected(pernet->path_manager, true); + if (pm) + bpf_module_put(pm, pm->owner); } =20 static struct pernet_operations mptcp_pernet_ops =3D { --=20 2.43.0 From nobody Mon Aug 24 01:40:34 2026 Received: from mta1.migadu.com (out-61.mta1.migadu.com [95.215.58.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7DED43F4AA for ; Tue, 18 Aug 2026 09:48:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.61 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046537; cv=none; b=nT2MfHdceCuEScMyj3IdwGQZECJVAD9d6lX1rYGonoUjzLwsg0KYV74f/1uBO66OtqZ0SxIFl+ug1jKJUdrXqh2QzKW+jfZZoVcRWlc3WV+9gvlaUwO5MXCdQ7Tsw6wgWaLV1NaR+6PtVQE7A3owulX80t8c9f05MPPgJroUsSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787046537; c=relaxed/simple; bh=NSdLMyuCUdqkBCf9KMVvSC32qRaTcLIIV7XjRyKfEl8=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nXUi9azN6Ph4r0VEAa7xMXPT+qJJ9wZ44QhYkaKw32i9tWkxA4TdDtasscqnfQ16dj84tGT4L/FI2qZPJN+JMfRk4CbDts/YoV+7Hpo6FNsoFIKcZisX2j5LqEI2hzUtXw8YRhGxuLXAGghTBA2agfJrix4k0CfApssxzmkdVgU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=Cei67Gh6; arc=none smtp.client-ip=95.215.58.61 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="Cei67Gh6" X-Envelope-To: mptcp@lists.linux.dev DKIM-Signature: a=rsa-sha256; bh=NSdLMyuCUdqkBCf9KMVvSC32qRaTcLIIV7XjRyKfEl8=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787046533; v=1; x=1787651333; b=Cei67Gh6vWijeuY1n8jG4rVleuDQm3u2Xvr7ocv5HPrFALhGU0ZfhFH17VSztMFFFc9O9p4O ODW8Xhl1kHPLW04QVOWvQIMaEJDrkNhM17LhN1H5WBM0s8zwq2wHnDJV+54BH2FOs3eC8atxk8N tduhuXXiDXrVo62yniuG7Zos= X-Envelope-To: mptcp@lists.linux.dev Received: from thinkbook16p.. (223.70.159.239) by smtp.migadu.com with ESMTPS id d1dccfa21b7bc23d; Tue, 18 Aug 2026 09:48:53 +0000 X-Migadu-Flow: FLOW_OUT From: Gang Yan To: mptcp@lists.linux.dev Subject: [PATCH mptcp-next v2 5/5] Squash to "bpf: Add mptcp packet scheduler struct_ops" Date: Tue, 18 Aug 2026 17:48:25 +0800 Message-ID: <20260818094825.48446-6-gang.yan@linux.dev> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260818094825.48446-1-gang.yan@linux.dev> References: <20260818094825.48446-1-gang.yan@linux.dev> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gang Yan The pernet sysctl patches in this series swap the scheduler pointer with xchg() without taking any module reference: this is fine while ops can only be registered from built-in code. This commit is what makes BPF schedulers registerable, i.e. the first one whose ops can be unloaded while a pernet still stores them. Take the reference accordingly: - mptcp_pernet_set_defaults() pins &mptcp_sched_default, mirroring tcp_sk_init() pinning &tcp_reno; - mptcp_set_scheduler() takes a reference on the new ops and releases the one held on the ops it replaces, mirroring tcp_set_default_congestion_control(); - mptcp_net_exit() releases the last reference, mirroring tcp_sk_exit(). Assisted-by: Claude:GLM5.2 Co-developed-by: Tao Cui Signed-off-by: Tao Cui Signed-off-by: Gang Yan --- net/mptcp/ctrl.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c index 32268aa26097..309bbb2a4eb0 100644 --- a/net/mptcp/ctrl.c +++ b/net/mptcp/ctrl.c @@ -123,7 +123,8 @@ static void mptcp_pernet_set_defaults(struct mptcp_pern= et *pernet) pernet->stale_loss_cnt =3D 4; pernet->pm_type =3D MPTCP_PM_TYPE_KERNEL; =20 - RCU_INIT_POINTER(pernet->scheduler, &mptcp_sched_default); + if (bpf_try_module_get(&mptcp_sched_default, mptcp_sched_default.owner)) + RCU_INIT_POINTER(pernet->scheduler, &mptcp_sched_default); =20 if (bpf_try_module_get(&mptcp_pm_kernel, mptcp_pm_kernel.owner)) RCU_INIT_POINTER(pernet->path_manager, &mptcp_pm_kernel); @@ -134,15 +135,22 @@ static void mptcp_pernet_set_defaults(struct mptcp_pe= rnet *pernet) #ifdef CONFIG_SYSCTL static int mptcp_set_scheduler(struct mptcp_pernet *pernet, const char *na= me) { - struct mptcp_sched_ops *sched; + struct mptcp_sched_ops *sched, *prev; int ret =3D 0; =20 rcu_read_lock(); sched =3D mptcp_sched_find(name); - if (sched) - xchg(&pernet->scheduler, sched); - else + if (sched) { + if (bpf_try_module_get(sched, sched->owner)) { + prev =3D xchg(&pernet->scheduler, sched); + if (prev) + bpf_module_put(prev, prev->owner); + } else { + ret =3D -EBUSY; + } + } else { ret =3D -ENOENT; + } rcu_read_unlock(); =20 return ret; @@ -603,10 +611,15 @@ static int __net_init mptcp_net_init(struct net *net) static void __net_exit mptcp_net_exit(struct net *net) { struct mptcp_pernet *pernet =3D mptcp_get_pernet(net); + struct mptcp_sched_ops *sched; struct mptcp_pm_ops *pm; =20 mptcp_pernet_del_table(pernet); =20 + sched =3D rcu_dereference_protected(pernet->scheduler, true); + if (sched) + bpf_module_put(sched, sched->owner); + pm =3D rcu_dereference_protected(pernet->path_manager, true); if (pm) bpf_module_put(pm, pm->owner); --=20 2.43.0