[PATCH mptcp-next v7 3/9] mptcp: align struct mptcp_data_frag to 8 bytes on 32-bit

Geliang Tang <[email protected]> Fri, 17 Jul 2026 12:50:12 +0800
Newsgroups dev.linux.lists.mptcp
Message-ID <54e907886c661227cf62641ad46bc470344b3613.1784260668.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 1cab07b1b9b1..ca0c02f3bfd3 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