Bug 276363 - if_wg: Fix bug in calculate_padding() for the 'p_mtu = 0' case
Summary: if_wg: Fix bug in calculate_padding() for the 'p_mtu = 0' case
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: Kyle Evans
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-01-16 05:24 UTC by Aaron LI
Modified: 2024-01-30 05:47 UTC (History)
2 users (show)

See Also:
kevans: mfc-stable14+
kevans: mfc-stable13+
kevans: mfc-stable12-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Aaron LI 2024-01-16 05:24:32 UTC
The padding length calculation in calculate_padding() is wrong for the special case of 'p_mtu = 0'.  It's calculating the padded length instead of the length to pad.  So it should be:

if (__predict_false(!pkt->p_mtu))
	return ((last_unit + (WG_PKT_PADDING - 1)) & ~(WG_PKT_PADDING - 1)) - last_unit;

However, it's impossible for 'p_mtu' to be zero.  So I'd propose the following fix:

@@ -1461,8 +1461,7 @@ calculate_padding(struct wg_packet *pkt)
 {
 	unsigned int padded_size, last_unit = pkt->p_mbuf->m_pkthdr.len;
 
-	if (__predict_false(!pkt->p_mtu))
-		return (last_unit + (WG_PKT_PADDING - 1)) & ~(WG_PKT_PADDING - 1);
+	KASSERT(pkt->p_mtu != 0, ("%s: packet %p has p_mtu = 0", __func__, m));
 
 	if (__predict_false(last_unit > pkt->p_mtu))
 		last_unit %= pkt->p_mtu;
Comment 1 Aaron LI 2024-01-16 14:29:19 UTC
Well, after testing, I found 'pkt->p_mtu' is actually 0 for keepalive packets; however, those packets also have a zero length, so calculate_padding() didn't cause any real problems.

I suggest the following new patch:

--- if_wg.c.orig	2023-10-12 09:06:16.983637264 +0800
+++ if_wg.c	2024-01-16 22:25:04.878629478 +0800
@@ -1461,8 +1461,11 @@ calculate_padding(struct wg_packet *pkt)
 {
 	unsigned int padded_size, last_unit = pkt->p_mbuf->m_pkthdr.len;
 
-	if (__predict_false(!pkt->p_mtu))
-		return (last_unit + (WG_PKT_PADDING - 1)) & ~(WG_PKT_PADDING - 1);
+	/* Keepalive packets don't set p_mtu, but also have a zreo length. */
+	if (__predict_false(pkt->p_mtu == 0)) {
+		padded_size = (last_unit + (WG_PKT_PADDING - 1)) & ~(WG_PKT_PADDING - 1);
+		return padded_size - last_unit;
+	}
 
 	if (__predict_false(last_unit > pkt->p_mtu))
 		last_unit %= pkt->p_mtu;
Comment 2 Kyle Evans freebsd_committer freebsd_triage 2024-01-17 22:44:49 UTC
(In reply to Aaron LI from comment #1)

I would perhaps reorganize it slightly at that point:

static inline unsigned int                                                      
calculate_padding(struct wg_packet *pkt)                                        
{                                                                               
        unsigned int padded_size, last_unit = pkt->p_mbuf->m_pkthdr.len;        
                                                                                
        padded_size = (last_unit + (WG_PKT_PADDING - 1)) & ~(WG_PKT_PADDING - 1);
                                                                                   
        if (__predict_true(pkt->p_mtu != 0)) {                                  
                if (__predict_false(last_unit > pkt->p_mtu))                       
                        last_unit %= pkt->p_mtu;                                
                                                                                
                if (pkt->p_mtu < padded_size)                                   
                        padded_size = pkt->p_mtu;                               
        }                                                                       
                                                                                
        return (padded_size - last_unit);                                       
}
Comment 3 Kyle Evans freebsd_committer freebsd_triage 2024-01-17 23:13:12 UTC
(In reply to Kyle Evans from comment #2)

WHoops, sorry, of course we need to re-calculate padded_size.
Comment 4 commit-hook freebsd_committer freebsd_triage 2024-01-17 23:30:59 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=b891f61ef538a4e9b4658b4b756635c8036a5788

commit b891f61ef538a4e9b4658b4b756635c8036a5788
Author:     Aaron LI <aly@aaronly.me>
AuthorDate: 2024-01-17 23:29:23 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-01-17 23:29:52 +0000

    if_wg: fix erroneous calculation in calculate_padding() for p_mtu == 0

    In practice this is harmless; only keepalive packets may realistically have
    p_mtu == 0, and they'll also have no payload so the math works out the same
    either way.  Still, let's prefer technical accuracy and calculate the amount
    of padding needed rather than the padded length...

    PR:             276363

 sys/dev/wg/if_wg.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
Comment 5 commit-hook freebsd_committer freebsd_triage 2024-01-30 05:39:45 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=bbda52e814e0c760b2beaeae40a2c76ff43d1975

commit bbda52e814e0c760b2beaeae40a2c76ff43d1975
Author:     Aaron LI <aly@aaronly.me>
AuthorDate: 2024-01-17 23:29:23 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-01-30 05:37:46 +0000

    if_wg: fix erroneous calculation in calculate_padding() for p_mtu == 0

    In practice this is harmless; only keepalive packets may realistically have
    p_mtu == 0, and they'll also have no payload so the math works out the same
    either way.  Still, let's prefer technical accuracy and calculate the amount
    of padding needed rather than the padded length...

    PR:             276363

    (cherry picked from commit b891f61ef538a4e9b4658b4b756635c8036a5788)

 sys/dev/wg/if_wg.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
Comment 6 commit-hook freebsd_committer freebsd_triage 2024-01-30 05:39:47 UTC
A commit in branch stable/14 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=86986d381072171a5d6183701ae2f96c2d9a6406

commit 86986d381072171a5d6183701ae2f96c2d9a6406
Author:     Aaron LI <aly@aaronly.me>
AuthorDate: 2024-01-17 23:29:23 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-01-30 05:37:29 +0000

    if_wg: fix erroneous calculation in calculate_padding() for p_mtu == 0

    In practice this is harmless; only keepalive packets may realistically have
    p_mtu == 0, and they'll also have no payload so the math works out the same
    either way.  Still, let's prefer technical accuracy and calculate the amount
    of padding needed rather than the padded length...

    PR:             276363

    (cherry picked from commit b891f61ef538a4e9b4658b4b756635c8036a5788)

 sys/dev/wg/if_wg.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
Comment 7 Kyle Evans freebsd_committer freebsd_triage 2024-01-30 05:47:56 UTC
MFC'd to all supported branches; thanks!