From nobody Sun Jul 5 05:56:05 2026 Received: from sender4-of-o54.zoho.com (sender4-of-o54.zoho.com [136.143.188.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C8F74071E7 for ; Mon, 29 Jun 2026 12:08:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.54 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734908; cv=pass; b=PWACwu2sHU8qziI2oPk8mjIY5i7so3SIfxxx/1Cr7aqRG5i20mQaKfRifBnKWGAjHTFom0FOS5PquyzlFASCMCKl4FLQhfp3CdJvZgiiCLJ2kaH/nfVz17VZ3ryEzve08meIFQR8XCEtfsH+zx4/yeQG29TPPJp4LFl0GuuEodI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734908; c=relaxed/simple; bh=q5i0aSF2kkLypPb305UtsW8d/olZCupJeFCMmvKIrkk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MBfMggwxUOGqcN+5qk6qgrfjqjqHUfgyYMIJ4BSf3tvx4uSPFxefRGntMRO3jaEc6A779SYS6ZdrT/WLUY9Qww3nVXE5vQuuCa5PNjuP7MRO7h7S9b5lZjZIEIIG4/0ers0cCYYLGkSg+E517stmlmHoE879txr7wP6rWoByJac= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com; spf=pass smtp.mailfrom=mpiricsoftware.com; dkim=fail (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b=P7MVGtMc reason="key not found in DNS"; arc=pass smtp.client-ip=136.143.188.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b="P7MVGtMc" ARC-Seal: i=1; a=rsa-sha256; t=1782734892; cv=none; d=zohomail.com; s=zohoarc; b=gqR2RSNfSpYeuU5kUL/LhugCxyYQXiOUH0z5xZObRBzp1C5rNRtv1rJincKFufuDpCHXhzomqXzYrHWkkJQlYeOqTpoXt4wBQpjMKkO//FPkYSepNsaCs7/BOnEWsVlMMx56hYRsURB2In0uCpMA9+GBynYlyOBVy9L0w1lYGtw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1782734892; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=8QFw/XHYOGhjIW2BP+GoaEtVWkDrQfcVRvjs99OAAjw=; b=cMyZYRkpFrS0Ii6v0OKvlDg+ZFgkTQbXDrOA+jwmU1sHt92gW2zBNMVzshTJmWzNDEGPEfmUL1oboeTHQiovoE8wSDKrRPSKQ2FP3S1GwilHIKqg7R4XAMUOiwJ82igvEdDEcE7G1amHiOTj4oQStc1lhZgwZKbsMx1U+JCbco0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=mpiricsoftware.com; spf=pass smtp.mailfrom=shardul.b@mpiricsoftware.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782734892; s=mpiric; d=mpiricsoftware.com; i=shardul.b@mpiricsoftware.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:References:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=8QFw/XHYOGhjIW2BP+GoaEtVWkDrQfcVRvjs99OAAjw=; b=P7MVGtMcXGYGVzB+d9sbUWGvRmseNRBs6gWhU9eKjwMmVkKyqfjqL0d0T0phiz01 U0cHIaWdQCMTd0itQvhokV65l0vVU//C/cEs6Yb56Mk8ETB8qd/CDk1oc8NLecITiyA HUZxjd+Yp2kc6NXoZ2gSV+ugKnzM9Ejlrfe4AKo8= Received: by mx.zohomail.com with SMTPS id 1782734890635758.9205377284165; Mon, 29 Jun 2026 05:08:10 -0700 (PDT) From: Shardul Bankar Date: Mon, 29 Jun 2026 17:37:34 +0530 Subject: [PATCH mptcp-next 1/4] Squash to "bpf: Export mptcp packet scheduler helpers" Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260629-mptcp_bpf_kfunc_fixes-v1-1-8cc875f36f53@mpiricsoftware.com> References: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> In-Reply-To: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> To: mptcp@lists.linux.dev, Geliang Tang Cc: Matthieu Baerts , Mat Martineau , Paolo Abeni , kalpan.jani@mpiricsoftware.com, janak@mpiric.us, shardulsb08@gmail.com, Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External mptcp_set_timeout() is exposed to BPF MPTCP packet schedulers as a kfunc taking a generic "struct sock *". The verifier only checks that the argument is a trusted struct sock; it cannot distinguish an MPTCP-level socket (msk) from a subflow's TCP socket. A scheduler get_send() program can therefore pass a subflow socket (e.g. msk->first, or the result of bpf_mptcp_subflow_tcp_sock()), which mptcp_set_timeout() upcasts via mptcp_sk() and iterates as msk->conn_list. On a subflow socket those bytes are live TCP state, so the walk yields a wild mptcp_subflow_context and the subsequent subflow->tcp_sock dereference faults (GPF / KASAN user-memory-access). Narrow the kfunc-facing type: register a bpf_mptcp_set_timeout() wrapper taking "struct mptcp_sock *" instead of the raw mptcp_set_timeout() symbol, so the verifier's BTF-id check rejects a non-msk socket at program load time. A scheduler that passes its msk is unaffected; update the in-tree burst scheduler selftest accordingly. Found by an MPTCP protocol-flow harness extending BRF (arXiv:2305.08782). Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Shardul Bankar --- net/mptcp/bpf.c | 7 ++++++- tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index 0845061ddc65c..9355fb53e89d5 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -301,6 +301,11 @@ bpf_sk_stream_memory_free(const struct mptcp_subflow_c= ontext *subflow) return false; } =20 +__bpf_kfunc static void bpf_mptcp_set_timeout(struct mptcp_sock *msk) +{ + mptcp_set_timeout((struct sock *)msk); +} + __bpf_kfunc_end_defs(); =20 BTF_KFUNCS_START(bpf_mptcp_iter_kfunc_ids) @@ -319,7 +324,7 @@ BTF_ID_FLAGS(func, bpf_mptcp_subflow_ctx, KF_RET_NULL) BTF_ID_FLAGS(func, bpf_mptcp_subflow_tcp_sock, KF_RET_NULL) BTF_ID_FLAGS(func, mptcp_subflow_set_scheduled) BTF_ID_FLAGS(func, mptcp_subflow_active) -BTF_ID_FLAGS(func, mptcp_set_timeout) +BTF_ID_FLAGS(func, bpf_mptcp_set_timeout) BTF_ID_FLAGS(func, mptcp_wnd_end) BTF_ID_FLAGS(func, bpf_sk_stream_memory_free) BTF_ID_FLAGS(func, mptcp_pm_subflow_chk_stale, KF_SLEEPABLE) diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c b/tools/te= sting/selftests/bpf/progs/mptcp_bpf_burst.c index 8ff529d38a595..1c4673d7c2338 100644 --- a/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c @@ -22,7 +22,7 @@ struct bpf_subflow_send_info { #define RB_EMPTY_ROOT(root) (READ_ONCE((root)->rb_node) =3D=3D NULL) =20 extern bool mptcp_subflow_active(struct mptcp_subflow_context *subflow) __= ksym; -extern void mptcp_set_timeout(struct sock *sk) __ksym; +extern void bpf_mptcp_set_timeout(struct mptcp_sock *msk) __ksym; extern __u64 mptcp_wnd_end(const struct mptcp_sock *msk) __ksym; extern bool bpf_sk_stream_memory_free(const struct mptcp_subflow_context *= subflow) __ksym; extern void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struc= t sock *ssk) __ksym; @@ -99,7 +99,7 @@ int BPF_PROG(bpf_burst_get_send, struct mptcp_sock *msk) send_info[backup].linger_time =3D linger_time; } } - mptcp_set_timeout(sk); + bpf_mptcp_set_timeout(msk); =20 /* pick the best backup if no other subflow is active */ if (!nr_active) --=20 2.34.1 From nobody Sun Jul 5 05:56:05 2026 Received: from sender4-of-o54.zoho.com (sender4-of-o54.zoho.com [136.143.188.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 973CF344D88 for ; Mon, 29 Jun 2026 12:08:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.54 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734928; cv=pass; b=XkavND06T0w7j2DJjHfAkzODtcqslDxDfc78CuFb3b2D5hBwwB0WyRPYWL+8f80nf9iHYSa63WGzp3Zu5OHmvUiYXqHohGs5Krp+GgReBpAOfxdKRAMd3dfnLWEHVjugc8wE56S2hxWMyy30ZrcCyx8tykspt/R3hs5ksbUjSFY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734928; c=relaxed/simple; bh=NDMSGViNeJXiTb4XTXSDt42GklPTcd1BjKE0R+OLXtA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VAqzR/eQBtbvLqkwTYYflY11UDh/rlmfY0BSA48LF7JuYksUZIPh6fdlBOi1ZH+WCxadsHod8bZhPYxa6yLQcLM8VupEReBohKazp8evDf53ONIPkclNE+zr8cb40Q6EK7QchAcHchMGW8QHVaWm9M1r99+3aXxH3pzD0QHdTxM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com; spf=pass smtp.mailfrom=mpiricsoftware.com; dkim=fail (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b=ROPUcLxL reason="key not found in DNS"; arc=pass smtp.client-ip=136.143.188.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b="ROPUcLxL" ARC-Seal: i=1; a=rsa-sha256; t=1782734896; cv=none; d=zohomail.com; s=zohoarc; b=kl2TH8AWtdyX1DJca5GsPaGlC+1vQ1ZVAgBOSeXoFjhw0BsDPyCez8z9g2Dacm0moWmgxXtIRtAMJ+oorRLqgvjeBbQhyNJ78ywmFFUAq9QI81UeFX7QEAGaPIpDfyJDM4gw5iltZyzCKdMMfGepJbgNPMNL2Hf9yr95OEqWOeM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1782734896; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=6uBz/Og5lkQ0n7sGZjz4+Usf3ATC4fD81HYsYh8Uf+I=; b=EnDqgWCUaBTtkcFnO5S8B3aM2Aq2ktHHDo8muZNX+kjfZu+fvILGfXI0wSqmDhdFF1DMRPJlrna3Qotgw3/3HW14Bk03P9n2wy9Dq9BJID2LTrQqnPQQ0MWP6sDhJQb18aeL+5qwiZ7wExNjLx94JoxOy063X46eE3mcH8osydo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=mpiricsoftware.com; spf=pass smtp.mailfrom=shardul.b@mpiricsoftware.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782734896; s=mpiric; d=mpiricsoftware.com; i=shardul.b@mpiricsoftware.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:References:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=6uBz/Og5lkQ0n7sGZjz4+Usf3ATC4fD81HYsYh8Uf+I=; b=ROPUcLxLJO4pOoCG4BQ2jWpGWxbOs9XhbRcBep1nL6Patgar77KgZ63TCvqeqF3Y yTwkGK7K6lrvjkRrF9weEDZGhzuX4IEI9ExV5xSb6GePsMJdwTwufsQYn5Qzfyes5Em 22Ebj/VyTEbykspcI+XdjEk3noj4WYOiBXe2ousE= Received: by mx.zohomail.com with SMTPS id 1782734894576889.2873021767887; Mon, 29 Jun 2026 05:08:14 -0700 (PDT) From: Shardul Bankar Date: Mon, 29 Jun 2026 17:37:35 +0530 Subject: [PATCH mptcp-next 2/4] Squash to "bpf: Export mptcp packet scheduler helpers" Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260629-mptcp_bpf_kfunc_fixes-v1-2-8cc875f36f53@mpiricsoftware.com> References: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> In-Reply-To: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> To: mptcp@lists.linux.dev, Geliang Tang Cc: Matthieu Baerts , Mat Martineau , Paolo Abeni , kalpan.jani@mpiricsoftware.com, janak@mpiric.us, shardulsb08@gmail.com, Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External mptcp_pm_subflow_chk_stale() is exposed to BPF MPTCP packet schedulers as a kfunc whose second argument is a generic "struct sock *ssk". The verifier only checks that the argument is a trusted struct sock; it cannot tell a subflow's TCP socket from any other socket. A scheduler get_retrans() program can therefore pass a non-subflow socket (e.g. (struct sock *)msk, or any other full socket), and mptcp_pm_subflow_chk_stale() reinterprets it via mptcp_subflow_ctx(), which is an unchecked cast of inet_csk(ssk)->icsk_ulp_data. On a non-subflow socket the derived subflow is bogus, and the function reads tcp_sk(ssk) state and writes through that bogus pointer (subflow->stale_rcv_tstamp, subflow->stale_count). This kfunc legitimately operates on a subflow TCP socket, so the fix is a runtime role check rather than a narrower arg type: register a bpf_mptcp_pm_subflow_chk_stale() wrapper that validates ssk is a full MPTCP subflow TCP socket before calling the internal helper, like bpf_mptcp_subflow_ctx(). A scheduler passing a real subflow socket is unaffected; update the in-tree burst scheduler selftest accordingly. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Shardul Bankar --- net/mptcp/bpf.c | 10 +++++++++- tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/net/mptcp/bpf.c b/net/mptcp/bpf.c index 9355fb53e89d5..30d3cbb23efb0 100644 --- a/net/mptcp/bpf.c +++ b/net/mptcp/bpf.c @@ -306,6 +306,14 @@ __bpf_kfunc static void bpf_mptcp_set_timeout(struct m= ptcp_sock *msk) mptcp_set_timeout((struct sock *)msk); } =20 +__bpf_kfunc static void +bpf_mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *= ssk) +{ + if (ssk && sk_fullsock(ssk) && ssk->sk_type =3D=3D SOCK_STREAM && + ssk->sk_protocol =3D=3D IPPROTO_TCP && sk_is_mptcp(ssk)) + mptcp_pm_subflow_chk_stale(msk, ssk); +} + __bpf_kfunc_end_defs(); =20 BTF_KFUNCS_START(bpf_mptcp_iter_kfunc_ids) @@ -327,7 +335,7 @@ BTF_ID_FLAGS(func, mptcp_subflow_active) BTF_ID_FLAGS(func, bpf_mptcp_set_timeout) BTF_ID_FLAGS(func, mptcp_wnd_end) BTF_ID_FLAGS(func, bpf_sk_stream_memory_free) -BTF_ID_FLAGS(func, mptcp_pm_subflow_chk_stale, KF_SLEEPABLE) +BTF_ID_FLAGS(func, bpf_mptcp_pm_subflow_chk_stale, KF_SLEEPABLE) BTF_KFUNCS_END(bpf_mptcp_common_kfunc_ids) =20 static int bpf_mptcp_common_kfunc_filter(const struct bpf_prog *prog, u32 = kfunc_id) diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c b/tools/te= sting/selftests/bpf/progs/mptcp_bpf_burst.c index 1c4673d7c2338..408c65ed897b5 100644 --- a/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_burst.c @@ -25,7 +25,7 @@ extern bool mptcp_subflow_active(struct mptcp_subflow_con= text *subflow) __ksym; extern void bpf_mptcp_set_timeout(struct mptcp_sock *msk) __ksym; extern __u64 mptcp_wnd_end(const struct mptcp_sock *msk) __ksym; extern bool bpf_sk_stream_memory_free(const struct mptcp_subflow_context *= subflow) __ksym; -extern void mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, struc= t sock *ssk) __ksym; +extern void bpf_mptcp_pm_subflow_chk_stale(const struct mptcp_sock *msk, s= truct sock *ssk) __ksym; =20 static __always_inline __u64 div_u64(__u64 dividend, __u32 divisor) { @@ -140,7 +140,7 @@ int BPF_PROG(bpf_burst_get_retrans, struct mptcp_sock *= msk) =20 /* still data outstanding at TCP level? skip this */ if (!tcp_rtx_and_write_queues_empty(ssk)) { - mptcp_pm_subflow_chk_stale(msk, ssk); + bpf_mptcp_pm_subflow_chk_stale(msk, ssk); min_stale_count =3D min(min_stale_count, subflow->stale_count); continue; } --=20 2.34.1 From nobody Sun Jul 5 05:56:05 2026 Received: from sender4-of-o54.zoho.com (sender4-of-o54.zoho.com [136.143.188.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 521873FFF9B for ; Mon, 29 Jun 2026 12:08:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.54 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734938; cv=pass; b=SDr84cP/LkPnNmV0EEY+6rVUlweG+P5Y4qP3H0f+Y32f6N5dxtZaUOs+JJwFzhuGdTqRNFZ8lZ6bHBbL6o4Rjt6QD863tXymWuODrE3uVmkVye+xu3gUQen7eYWHMu83dbnFkwZ8RCktnMjDQnc/XwPbl7MWaUl2oYVtsnxY2yo= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734938; c=relaxed/simple; bh=QXV4rMsLXwskUUDUkDiE7569uoQ7A8ycu/EnXxHwUIU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J7bxwCm3QLBtmCOSRnvehnjKNJaBWZjaeB8FLjCNaDipfAsPK88kZdb+zbm3Se/cAGj+w/Q08AEG2+ApGVPCeNPm+8Q7rvyfx+5czldu7idzHtOApDuwLwilxhGYlvFYyKW1vrOAOb9FJb3n6gwuSomdymFHMXHtln061Z15DEQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com; spf=pass smtp.mailfrom=mpiricsoftware.com; dkim=fail (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b=Nen65Kx3 reason="key not found in DNS"; arc=pass smtp.client-ip=136.143.188.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b="Nen65Kx3" ARC-Seal: i=1; a=rsa-sha256; t=1782734900; cv=none; d=zohomail.com; s=zohoarc; b=IyFje8sKLxJ1n+sMV8btIDzDneU2mNcd3y6G6OgN9gbxrOfQuY4+/dCMj4f+Hq+rCiVoWVS74C8wx7TQkc3o0AHZ0lS60I6O72ElhLJHr+N8PT9g3mPLvf0uBT/paHb/PgIpnyCmb9jRm6AuDPVgenp4fBihWnsxJi2OE+alv/0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1782734900; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=2Og1XzI6rzxWO6z7+CakZEkwmnxHyX9Og19BJ4EcMGs=; b=AUExO/vSHI+UtRnaLXqgBsl7Ym52Cjd9YEK0nJrdxJhXnQHcpgxYwRK3GQ14BAG1wpcTue+r8nLifVCGQcWYTfU6tUbpN6ILkCsNKzPDWgxsST6p09RFH6MNY1a56KDNBjPSewJoRw+7Y5dbEe8LVXhzbGy+QN4CO1eALkS/TPg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=mpiricsoftware.com; spf=pass smtp.mailfrom=shardul.b@mpiricsoftware.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782734900; s=mpiric; d=mpiricsoftware.com; i=shardul.b@mpiricsoftware.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:References:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=2Og1XzI6rzxWO6z7+CakZEkwmnxHyX9Og19BJ4EcMGs=; b=Nen65Kx3wizR2YXzpMQryJxGeDD6VU0bBGGSb2EfpyB3cjc9IY5mbE/prd+v2WSE OX/QIdAWysVeQChywVanj0i8we6wZxJh5LeDytvcHIacFJMBZs0zXLdRHOea2uOo/3z HOP38zMwqJnsjTp8h8Kd/J9TxQW24wl4lZB6TIU8= Received: by mx.zohomail.com with SMTPS id 1782734898475724.6580826874817; Mon, 29 Jun 2026 05:08:18 -0700 (PDT) From: Shardul Bankar Date: Mon, 29 Jun 2026 17:37:36 +0530 Subject: [PATCH mptcp-next 3/4] selftests/bpf: mptcp: verify scheduler rejects non-msk socket to set_timeout Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260629-mptcp_bpf_kfunc_fixes-v1-3-8cc875f36f53@mpiricsoftware.com> References: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> In-Reply-To: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> To: mptcp@lists.linux.dev, Geliang Tang Cc: Matthieu Baerts , Mat Martineau , Paolo Abeni , kalpan.jani@mpiricsoftware.com, janak@mpiric.us, shardulsb08@gmail.com, Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External Add a negative test for the bpf_mptcp_set_timeout() kfunc: a BPF MPTCP scheduler whose get_send() passes a subflow TCP socket to it, where the kfunc takes a struct mptcp_sock *, must be rejected by the verifier at program load time. This guards against widening the kfunc argument back to a generic struct sock *, which would reintroduce the socket type confusion between an MPTCP-level socket and a subflow TCP socket. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Shardul Bankar --- tools/testing/selftests/bpf/prog_tests/mptcp.c | 31 +++++++++++++ .../selftests/bpf/progs/mptcp_bpf_bad_sched.c | 54 ++++++++++++++++++= ++++ 2 files changed, 85 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing= /selftests/bpf/prog_tests/mptcp.c index 7f48fd9e94e1e..ff8209ebc8388 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -18,6 +18,7 @@ #include "mptcp_bpf_rr.skel.h" #include "mptcp_bpf_red.skel.h" #include "mptcp_bpf_burst.skel.h" +#include "mptcp_bpf_bad_sched.skel.h" =20 #define NS_TEST "mptcp_ns" #define ADDR_1 "10.0.1.1" @@ -813,6 +814,34 @@ static void test_burst(void) mptcp_bpf_burst__destroy(skel); } =20 +static void test_bad_sched(void) +{ + struct mptcp_bpf_bad_sched *skel; + char *log =3D NULL; + int err; + + /* bad_sched_get_send() passes a subflow TCP socket to + * bpf_mptcp_set_timeout(), which takes a struct mptcp_sock *. The + * verifier must reject this socket type confusion at load time, and + * for the right reason -- assert the specific verifier message. + */ + skel =3D mptcp_bpf_bad_sched__open(); + if (!ASSERT_OK_PTR(skel, "open: bad_sched")) + return; + + if (start_libbpf_log_capture()) + goto destroy; + + err =3D mptcp_bpf_bad_sched__load(skel); + log =3D stop_libbpf_log_capture(); + ASSERT_ERR(err, "load: bad_sched must be rejected"); + ASSERT_HAS_SUBSTR(log, "expected pointer to STRUCT mptcp_sock", + "verifier rejects subflow sock to bpf_mptcp_set_timeout"); + free(log); +destroy: + mptcp_bpf_bad_sched__destroy(skel); +} + void test_mptcp(void) { if (test__start_subtest("base")) @@ -835,4 +864,6 @@ void test_mptcp(void) test_red(); if (test__start_subtest("burst")) test_burst(); + if (test__start_subtest("bad_sched")) + test_bad_sched(); } diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_bad_sched.c b/tool= s/testing/selftests/bpf/progs/mptcp_bpf_bad_sched.c new file mode 100644 index 0000000000000..14041c1e5ffd7 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_bad_sched.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026, Mpiric Software. */ + +/* A scheduler that passes a subflow TCP socket to bpf_mptcp_set_timeout(), + * which takes a struct mptcp_sock *. The verifier must reject this at load + * time; see the bad_sched subtest in prog_tests/mptcp.c. + */ +#include "mptcp_bpf.h" +#include + +char _license[] SEC("license") =3D "GPL"; + +extern void bpf_mptcp_set_timeout(struct mptcp_sock *msk) __ksym; + +SEC("struct_ops") +void BPF_PROG(bad_sched_init, struct mptcp_sock *msk) +{ +} + +SEC("struct_ops") +void BPF_PROG(bad_sched_release, struct mptcp_sock *msk) +{ +} + +SEC("struct_ops") +int BPF_PROG(bad_sched_get_send, struct mptcp_sock *msk) +{ + struct mptcp_subflow_context *subflow; + struct sock *ssk; + + bpf_for_each(mptcp_subflow, subflow, (struct sock *)msk) { + ssk =3D bpf_mptcp_subflow_tcp_sock(subflow); + if (!ssk) + return -1; + /* ssk is a subflow TCP socket (struct sock *), not an msk. + * Passing it to bpf_mptcp_set_timeout(), which takes a + * struct mptcp_sock *, is a socket type confusion that the + * verifier must reject at load time ("expected pointer to + * STRUCT mptcp_sock"). + */ + bpf_mptcp_set_timeout((struct mptcp_sock *)ssk); + mptcp_subflow_set_scheduled(subflow, true); + return 0; + } + return -1; +} + +SEC(".struct_ops.link") +struct mptcp_sched_ops bad_sched =3D { + .init =3D (void *)bad_sched_init, + .release =3D (void *)bad_sched_release, + .get_send =3D (void *)bad_sched_get_send, + .name =3D "bpf_bad_sched", +}; --=20 2.34.1 From nobody Sun Jul 5 05:56:05 2026 Received: from sender4-of-o54.zoho.com (sender4-of-o54.zoho.com [136.143.188.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 68B4B3FFFA9 for ; Mon, 29 Jun 2026 12:09:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.54 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734948; cv=pass; b=YGwIeyiT8qmfaPgSwea7w3v3AzDSoB9r+RJFrGtyoVlHim1jzJ8wYYC1DkcXSISzZXHQBYF9TRr+RKKuQ/kYdEu6uf+dAR+KHp/Y+bPKNkdG1+dVb7VYros79lnSdqHX/SP91Ttk8rijsgx1lq7LjzLVRU/bopuluwUC6vUE9d4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782734948; c=relaxed/simple; bh=EttVtN54NpoGL7JfXlrlA4qAUNyNqkIw/Bu0aeGrzfY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J9qgSgEFAWYXKPPpiS5tPnbuL14G9kln1YkBCGzyI3G83Zs+uLHhwzvkBvInZQDrjMuanHjYLLMAjAZrFMwbuZ/76y/aaahsAerMQ/wNBRxWJZNby0OAYdnBHkIyqfLbY7zsvIkHvtX7D+WOoX3zDFc8JhLYyK9pXTOxHfLIOCo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com; spf=pass smtp.mailfrom=mpiricsoftware.com; dkim=fail (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b=FRvH69if reason="key not found in DNS"; arc=pass smtp.client-ip=136.143.188.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mpiricsoftware.com Authentication-Results: smtp.subspace.kernel.org; dkim=fail reason="key not found in DNS" (0-bit key) header.d=mpiricsoftware.com header.i=shardul.b@mpiricsoftware.com header.b="FRvH69if" ARC-Seal: i=1; a=rsa-sha256; t=1782734904; cv=none; d=zohomail.com; s=zohoarc; b=PtukDSFkcRP9Gfpk/A0LIm8v0UkSdRjBBCx5GAcGug1HWTzS0OgdCUKxxXBTEc1dg3toTit6N2fQHsW+lY6snnmDGcDs4Vnf+ME/SihcnG909lw+RIhRjmZ+DWVvMIrNEeyE+KSj1oi8Uk8BqLASHU/XglJlKccekeD9nLO+ZJ0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1782734904; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=ph5R66zjCHV6C8PjS/H7PwukS1lyNzE3pnl9UKB78Jc=; b=A8hABng3QedY+r43wWAMD8fgqJY2gzweGwdzeHEsV47k0YaJGbm6rfwfMXSU6H9ZvvzM1CfSkSwcafL3KPMC6jNefNHd9grxoN5FZvIE4cUzBDNmLgdtDwExZDPu09BAnqSXp35rfZ/JcSoHAvQe1G+jzinPz8ao1AwrqfsSS8c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=mpiricsoftware.com; spf=pass smtp.mailfrom=shardul.b@mpiricsoftware.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1782734904; s=mpiric; d=mpiricsoftware.com; i=shardul.b@mpiricsoftware.com; h=From:From:Date:Date:Subject:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:Message-Id:References:In-Reply-To:To:To:Cc:Cc:Reply-To; bh=ph5R66zjCHV6C8PjS/H7PwukS1lyNzE3pnl9UKB78Jc=; b=FRvH69if6FyKUP8yDlKbfdle9AWk/27f5kROraU4qShTZdLzBTfjW+iA01g9r1RF iDaa4vLhm7sjOGgTcPfS1yU9fTmTEdadcYeO6fsXOhfnBmOLs1k1YKeTup0Nt28B3Zz ssVoma2u1+hUT/tefoUwOs8m6bJWbSsHcVDyiwPI= Received: by mx.zohomail.com with SMTPS id 1782734902250143.41331820486255; Mon, 29 Jun 2026 05:08:22 -0700 (PDT) From: Shardul Bankar Date: Mon, 29 Jun 2026 17:37:37 +0530 Subject: [PATCH mptcp-next 4/4] selftests/bpf: mptcp: extend bad scheduler test to the kfunc type contract Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260629-mptcp_bpf_kfunc_fixes-v1-4-8cc875f36f53@mpiricsoftware.com> References: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> In-Reply-To: <20260629-mptcp_bpf_kfunc_fixes-v1-0-8cc875f36f53@mpiricsoftware.com> To: mptcp@lists.linux.dev, Geliang Tang Cc: Matthieu Baerts , Mat Martineau , Paolo Abeni , kalpan.jani@mpiricsoftware.com, janak@mpiric.us, shardulsb08@gmail.com, Shardul Bankar X-Mailer: b4 0.15.2 X-ZohoMailClient: External The bad_sched test covers one socket type confusion: a subflow TCP socket passed to bpf_mptcp_set_timeout(), which takes a struct mptcp_sock *. Extend it into a small suite that guards the narrow-typed scheduler kfunc surface against that bug class, covering both confusion directions: - a subflow sock passed to mptcp_wnd_end() (struct mptcp_sock *), the same direction as the set_timeout case; - the msk passed to mptcp_subflow_set_scheduled() (struct mptcp_subflow_context *), the inverse direction. Each malicious scheduler is its own struct_ops map. They are loaded one at a time via bpf_map__set_autocreate(), so each load failure is checked against its own verifier type-mismatch message. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Shardul Bankar --- tools/testing/selftests/bpf/prog_tests/mptcp.c | 56 ++++++++++++++++--= ---- .../selftests/bpf/progs/mptcp_bpf_bad_sched.c | 46 ++++++++++++++++++ 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/mptcp.c b/tools/testing= /selftests/bpf/prog_tests/mptcp.c index ff8209ebc8388..76a112d56f358 100644 --- a/tools/testing/selftests/bpf/prog_tests/mptcp.c +++ b/tools/testing/selftests/bpf/prog_tests/mptcp.c @@ -814,31 +814,57 @@ static void test_burst(void) mptcp_bpf_burst__destroy(skel); } =20 -static void test_bad_sched(void) +static void load_bad_sched(struct mptcp_bpf_bad_sched *skel, const char *m= sg) { - struct mptcp_bpf_bad_sched *skel; char *log =3D NULL; int err; =20 - /* bad_sched_get_send() passes a subflow TCP socket to - * bpf_mptcp_set_timeout(), which takes a struct mptcp_sock *. The - * verifier must reject this socket type confusion at load time, and - * for the right reason -- assert the specific verifier message. + if (start_libbpf_log_capture()) + return; + + err =3D mptcp_bpf_bad_sched__load(skel); + log =3D stop_libbpf_log_capture(); + ASSERT_ERR(err, "load: bad scheduler must be rejected"); + ASSERT_HAS_SUBSTR(log, msg, "verifier type-mismatch message"); + free(log); +} + +static void test_bad_sched(void) +{ + struct mptcp_bpf_bad_sched *skel; + + /* Each scheduler in mptcp_bpf_bad_sched passes a wrong-subtype socket + * to a narrow-typed scheduler kfunc; the verifier must reject each at + * load time with the specific type-mismatch message. The skel holds + * several such schedulers, so enable one struct_ops map at a time -- + * loading them together would fail atomically. */ + + /* subflow sock -> bpf_mptcp_set_timeout(struct mptcp_sock *) */ skel =3D mptcp_bpf_bad_sched__open(); if (!ASSERT_OK_PTR(skel, "open: bad_sched")) return; + bpf_map__set_autocreate(skel->maps.bad_wnd_end, false); + bpf_map__set_autocreate(skel->maps.bad_set_sched, false); + load_bad_sched(skel, "expected pointer to STRUCT mptcp_sock"); + mptcp_bpf_bad_sched__destroy(skel); =20 - if (start_libbpf_log_capture()) - goto destroy; + /* subflow sock -> mptcp_wnd_end(struct mptcp_sock *) */ + skel =3D mptcp_bpf_bad_sched__open(); + if (!ASSERT_OK_PTR(skel, "open: bad_wnd_end")) + return; + bpf_map__set_autocreate(skel->maps.bad_sched, false); + bpf_map__set_autocreate(skel->maps.bad_set_sched, false); + load_bad_sched(skel, "expected pointer to STRUCT mptcp_sock"); + mptcp_bpf_bad_sched__destroy(skel); =20 - err =3D mptcp_bpf_bad_sched__load(skel); - log =3D stop_libbpf_log_capture(); - ASSERT_ERR(err, "load: bad_sched must be rejected"); - ASSERT_HAS_SUBSTR(log, "expected pointer to STRUCT mptcp_sock", - "verifier rejects subflow sock to bpf_mptcp_set_timeout"); - free(log); -destroy: + /* msk -> mptcp_subflow_set_scheduled(struct mptcp_subflow_context *) */ + skel =3D mptcp_bpf_bad_sched__open(); + if (!ASSERT_OK_PTR(skel, "open: bad_set_sched")) + return; + bpf_map__set_autocreate(skel->maps.bad_sched, false); + bpf_map__set_autocreate(skel->maps.bad_wnd_end, false); + load_bad_sched(skel, "expected pointer to STRUCT mptcp_subflow_context"); mptcp_bpf_bad_sched__destroy(skel); } =20 diff --git a/tools/testing/selftests/bpf/progs/mptcp_bpf_bad_sched.c b/tool= s/testing/selftests/bpf/progs/mptcp_bpf_bad_sched.c index 14041c1e5ffd7..ce853ec6d73da 100644 --- a/tools/testing/selftests/bpf/progs/mptcp_bpf_bad_sched.c +++ b/tools/testing/selftests/bpf/progs/mptcp_bpf_bad_sched.c @@ -11,6 +11,7 @@ char _license[] SEC("license") =3D "GPL"; =20 extern void bpf_mptcp_set_timeout(struct mptcp_sock *msk) __ksym; +extern __u64 mptcp_wnd_end(const struct mptcp_sock *msk) __ksym; =20 SEC("struct_ops") void BPF_PROG(bad_sched_init, struct mptcp_sock *msk) @@ -52,3 +53,48 @@ struct mptcp_sched_ops bad_sched =3D { .get_send =3D (void *)bad_sched_get_send, .name =3D "bpf_bad_sched", }; + +/* Same confusion class as bad_sched, on another struct mptcp_sock * kfunc: + * feed a subflow TCP socket to mptcp_wnd_end(). The verifier must reject = it + * ("expected pointer to STRUCT mptcp_sock"). get_send is the only required + * scheduler op, so the rest are omitted. + */ +SEC("struct_ops") +int BPF_PROG(bad_wnd_end_get_send, struct mptcp_sock *msk) +{ + struct mptcp_subflow_context *subflow; + struct sock *ssk; + + bpf_for_each(mptcp_subflow, subflow, (struct sock *)msk) { + ssk =3D bpf_mptcp_subflow_tcp_sock(subflow); + if (!ssk) + return -1; + if (mptcp_wnd_end((struct mptcp_sock *)ssk)) + return 0; + return -1; + } + return -1; +} + +SEC(".struct_ops.link") +struct mptcp_sched_ops bad_wnd_end =3D { + .get_send =3D (void *)bad_wnd_end_get_send, + .name =3D "bpf_bad_wnd_end", +}; + +/* Inverse confusion: feed the msk to mptcp_subflow_set_scheduled(), which + * takes a struct mptcp_subflow_context *. The verifier must reject it + * ("expected pointer to STRUCT mptcp_subflow_context"). + */ +SEC("struct_ops") +int BPF_PROG(bad_set_sched_get_send, struct mptcp_sock *msk) +{ + mptcp_subflow_set_scheduled((struct mptcp_subflow_context *)msk, true); + return 0; +} + +SEC(".struct_ops.link") +struct mptcp_sched_ops bad_set_sched =3D { + .get_send =3D (void *)bad_set_sched_get_send, + .name =3D "bpf_bad_set_sch", +}; --=20 2.34.1