[PATCH mptcp-next v6 04/10] mptcp: align struct mptcp_data_frag to 8 bytes on 32-bit

Geliang Tang <[email protected]> Thu, 16 Jul 2026 15:50:43 +0800
Newsgroups dev.linux.lists.mptcp
Message-ID <fde91a05b425374188400a291bd91058a5017217.1784188064.git.tanggeliang@kylinos.cn>
From: Geliang Tang <[email protected]>

mptcp_carve_data_frag() places a struct mptcp_data_frag inside a
page-frag region, using ALIGN(orig_offset, sizeof(long)) to compute
the offset where the struct lives. On 64-bit Linux sizeof(long) is 8
and this works as intended. On 32-bit Linux sizeof(long) is 4, which
only guarantees 4-byte alignment for the struct.

struct mptcp_data_frag contains a u64 data_seq member, which requires
8-byte alignment. 4-byte-aligned 64-bit loads fault on 32-bit
architectures that do not handle unaligned 64-bit accesses in
hardware (armv7, mips, sparc, ...). The in-source comment near
BUILD_BUG_ON that states "ALIGN(1, sizeof(long)) - 1, so 8-1" is
misleading because it implicitly assumes sizeof(long) is always 8.

Switch both the ALIGN() and the matching BUILD_BUG_ON to sizeof(u64)
so the 8-byte alignment is enforced on every architecture, and the
overhead u8 budget still fits the worst-case 7-byte padding plus the
struct size. This is a no-op on 64-bit and a correctness fix on
32-bit.

Signed-off-by: Geliang Tang <[email protected]>
---
 net/mptcp/protocol.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 3acd61ae6160..7ad3a4a09e3b 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1237,7 +1237,7 @@ static struct mptcp_data_frag *
 mptcp_carve_data_frag(const struct mptcp_sock *msk, struct page_frag *pfrag,
 		      int orig_offset)
 {
-	int offset = ALIGN(orig_offset, sizeof(long));
+	int offset = ALIGN(orig_offset, sizeof(u64));
 	struct mptcp_data_frag *dfrag;
 
 	dfrag = (struct mptcp_data_frag *)(page_to_virt(pfrag->page) + offset);
@@ -4789,9 +4789,9 @@ void __init mptcp_proto_init(void)
 	BUILD_BUG_ON(sizeof(struct mptcp_skb_cb) > sizeof_field(struct sk_buff, cb));
 
 	/* struct mptcp_data_frag: 'overhead' corresponds to the alignment
-	 * (ALIGN(1, sizeof(long)) - 1, so 8-1) + the struct's size
+	 * (ALIGN(1, sizeof(u64)) - 1, so 8-1) + the struct's size
 	 */
-	BUILD_BUG_ON(ALIGN(1, sizeof(long)) - 1 + sizeof(struct mptcp_data_frag)
+	BUILD_BUG_ON(ALIGN(1, sizeof(u64)) - 1 + sizeof(struct mptcp_data_frag)
 		     > U8_MAX);
 }
 
-- 
2.53.0