[Openvpn-devel,v3] DCO Linux: Fix setting DCO ifmode failing on big endian archs

Message ID 20260219110954.21471-1-gert@greenie.muc.de
State New
Headers show
Series [Openvpn-devel,v3] DCO Linux: Fix setting DCO ifmode failing on big endian archs | expand

Commit Message

Gert Doering Feb. 19, 2026, 11:09 a.m. UTC
From: Arne Schwabe <arne@rfc2549.org>

The problem is that SITNL_ADDATTR is not forcing type safety and on
big endian architcutre passing a smaller size than the underlying
integer type of data causes only the more significant byte(s) to be passed
instead.

A proper fix would be to add specific methods for common integer types like
SITNL_ADDATTR_u8, SITNL_ADDATTR_u16, SITNL_ADDATTR_u32 like netlink library
does with NLA_PUT_U32, NLA_PUT_U16, NLA_PUT_U8.

Change-Id: I560f45fb0011180be8ca2b0e7fbc63030fa10f35
Github: closes OpenVPN/ovpn-dco#96
Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Antonio Quartulli <antonio@mandelbit.com>
Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1547
---

This change was reviewed on Gerrit and approved by at least one
developer. I request to merge it to master.

Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1547
This mail reflects revision 3 of this Change.

Acked-by according to Gerrit (reflected above):
Antonio Quartulli <antonio@mandelbit.com>

Comments

Gert Doering Feb. 19, 2026, 3:51 p.m. UTC | #1
Interesting catch, this :-) - I have tested this for "master" and "release/2.6"
on a regular Intel system, just to be sure there was no accidential breakage
on the other endiannes... (things still work).

Your patch has been applied to the master, release/2.7 and release/2.6 branch
(in 2.6, the "SITNL_ADDATTR()" line is wrapped differently, pre-clang-format
formatting, but that was trivially adjusted)

commit b3e0e8696b162794beefc22aad7406b328471cf6 (master)
commit 1c9f9bfa5c1f5e23036b1ffab683d926cd4c1aef (release/2.7)
commit a2037b264169530e7e6ee22007587369becec4be (release/2.6)
Author: Arne Schwabe
Date:   Thu Feb 19 12:09:48 2026 +0100

     DCO Linux: Fix setting DCO ifmode failing on big endian archs

     Signed-off-by: Arne Schwabe <arne@rfc2549.org>
     Acked-by: Antonio Quartulli <antonio@mandelbit.com>
     Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1547
     Message-Id: <20260219110954.21471-1-gert@greenie.muc.de>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg35752.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering

Patch

diff --git a/src/openvpn/networking_sitnl.c b/src/openvpn/networking_sitnl.c
index a5b2905..ad7edef 100644
--- a/src/openvpn/networking_sitnl.c
+++ b/src/openvpn/networking_sitnl.c
@@ -1337,7 +1337,15 @@ 
     {
         dco_context_t *dco = arg;
         struct rtattr *data = SITNL_NEST(&req.n, sizeof(req), IFLA_INFO_DATA);
-        SITNL_ADDATTR(&req.n, sizeof(req), IFLA_OVPN_MODE, &dco->ifmode, sizeof(uint8_t));
+
+        /* the netlink format is uint8_t for this and using something
+         * other than uint8_t here (enum underlying type is undefined but
+         * commonly int) causes the values to be 0 when passed
+         * on big endian arch as we only take the (biggest endian) byte
+         * directly at the address
+         */
+        uint8_t ifmode = (uint8_t)dco->ifmode;
+        SITNL_ADDATTR(&req.n, sizeof(req), IFLA_OVPN_MODE, &ifmode, sizeof(uint8_t));
         SITNL_NEST_END(&req.n, data);
     }
 #endif