netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP
  2025-07-03 11:45 [PATCH net 0/3] pull request: ovpn for net 2025-07-03 Antonio Quartulli
@ 2025-07-03 11:45 ` Antonio Quartulli
  2025-07-03 14:02   ` Sabrina Dubroca
  0 siblings, 1 reply; 7+ messages in thread
From: Antonio Quartulli @ 2025-07-03 11:45 UTC (permalink / raw)
  To: netdev
  Cc: Ralf Lici, Sabrina Dubroca, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Antonio Quartulli

From: Ralf Lici <ralf@mandelbit.com>

OpenVPN allows users to configure a FW mark on sockets used to
communicate with other peers. The mark is set by means of the
`SO_MARK` Linux socket option.

However, in the ovpn UDP code path, the socket's `sk_mark` value is
currently ignored and it is not propagated to outgoing `skbs`.

This commit ensures proper inheritance of the field by setting
`skb->mark` to `sk->sk_mark` before handing the `skb` to the network
stack for transmission.

Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Link: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31877.html
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/udp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c
index bff00946eae2..60435a21f29c 100644
--- a/drivers/net/ovpn/udp.c
+++ b/drivers/net/ovpn/udp.c
@@ -344,6 +344,7 @@ void ovpn_udp_send_skb(struct ovpn_peer *peer, struct sock *sk,
 	int ret;
 
 	skb->dev = peer->ovpn->dev;
+	skb->mark = READ_ONCE(sk->sk_mark);
 	/* no checksum performed at this layer */
 	skb->ip_summed = CHECKSUM_NONE;
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP
  2025-07-03 11:45 ` [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP Antonio Quartulli
@ 2025-07-03 14:02   ` Sabrina Dubroca
  0 siblings, 0 replies; 7+ messages in thread
From: Sabrina Dubroca @ 2025-07-03 14:02 UTC (permalink / raw)
  To: Antonio Quartulli
  Cc: netdev, Ralf Lici, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni

2025-07-03, 13:45:10 +0200, Antonio Quartulli wrote:
> From: Ralf Lici <ralf@mandelbit.com>
> 
> OpenVPN allows users to configure a FW mark on sockets used to
> communicate with other peers. The mark is set by means of the
> `SO_MARK` Linux socket option.
> 
> However, in the ovpn UDP code path, the socket's `sk_mark` value is
> currently ignored and it is not propagated to outgoing `skbs`.

Probably worth adding a small selftest? (not necessarily as part of
this series, though I think it would be ideal to have the fix and the
corresponding test together)

> This commit ensures proper inheritance of the field by setting
> `skb->mark` to `sk->sk_mark` before handing the `skb` to the network
> stack for transmission.
> 
> Signed-off-by: Ralf Lici <ralf@mandelbit.com>
> Link: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31877.html
> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>

A Fixes tag would be welcome for all those bugfixes. For this patch:

Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)")


With this:
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>

-- 
Sabrina

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net 0/3] pull request: ovpn for net 2025-07-16
@ 2025-07-16 11:54 Antonio Quartulli
  2025-07-16 11:54 ` [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP Antonio Quartulli
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Antonio Quartulli @ 2025-07-16 11:54 UTC (permalink / raw)
  To: netdev
  Cc: Antonio Quartulli, Sabrina Dubroca, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni

Hi netdev-team,
[2025-07-16: patch 2 reworked to use attribute subsets in yaml spec]

In this batch you can find the following bug fixes:

Patch 1: make sure to propagate any socket FW mark set by userspace
(via SO_MARK) to skbs being sent over that socket.

Patch 2: reject unexpected netlink attributes in user requests.
This was partly open-coded and partly implemented via ovpn.yaml spec.

Patch 3: reset the skb's GSO state when moving a packet from transport
to tunnel layer.

Please pull or let me know of any issue!

Thanks a lot.
Antonio,

The following changes since commit dae7f9cbd1909de2b0bccc30afef95c23f93e477:

  Merge branch 'mptcp-fix-fallback-related-races' (2025-07-15 17:31:30 -0700)

are available in the Git repository at:

  https://github.com/OpenVPN/ovpn-net-next tags/ovpn-net-20250716

for you to fetch changes up to 2022d704014d7a5b19dfe0a1ae5c67be0498e37c:

  ovpn: reset GSO metadata after decapsulation (2025-07-16 11:53:19 +0200)

----------------------------------------------------------------
This bugfix batch includes the following changes:
* properly propagate sk mark to skb->mark field
* reject unexpected incoming netlink attributes
* reset GSO state when moving skb from transport to tunnel layer

----------------------------------------------------------------
Antonio Quartulli (1):
      ovpn: reject unexpected netlink attributes

Ralf Lici (2):
      ovpn: propagate socket mark to skb in UDP
      ovpn: reset GSO metadata after decapsulation

 Documentation/netlink/specs/ovpn.yaml | 153 ++++++++++++++++++++++++++++++++--
 drivers/net/ovpn/io.c                 |   7 ++
 drivers/net/ovpn/netlink-gen.c        |  61 ++++++++++++--
 drivers/net/ovpn/netlink-gen.h        |   6 ++
 drivers/net/ovpn/netlink.c            |  51 ++++++++++--
 drivers/net/ovpn/udp.c                |   1 +
 6 files changed, 259 insertions(+), 20 deletions(-)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP
  2025-07-16 11:54 [PATCH net 0/3] pull request: ovpn for net 2025-07-16 Antonio Quartulli
@ 2025-07-16 11:54 ` Antonio Quartulli
  2025-07-17 14:50   ` patchwork-bot+netdevbpf
  2025-07-16 11:54 ` [PATCH net 2/3] ovpn: reject unexpected netlink attributes Antonio Quartulli
  2025-07-16 11:54 ` [PATCH net 3/3] ovpn: reset GSO metadata after decapsulation Antonio Quartulli
  2 siblings, 1 reply; 7+ messages in thread
From: Antonio Quartulli @ 2025-07-16 11:54 UTC (permalink / raw)
  To: netdev
  Cc: Ralf Lici, Sabrina Dubroca, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Antonio Quartulli

From: Ralf Lici <ralf@mandelbit.com>

OpenVPN allows users to configure a FW mark on sockets used to
communicate with other peers. The mark is set by means of the
`SO_MARK` Linux socket option.

However, in the ovpn UDP code path, the socket's `sk_mark` value is
currently ignored and it is not propagated to outgoing `skbs`.

This commit ensures proper inheritance of the field by setting
`skb->mark` to `sk->sk_mark` before handing the `skb` to the network
stack for transmission.

Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)")
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Link: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31877.html
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/udp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c
index bff00946eae2..60435a21f29c 100644
--- a/drivers/net/ovpn/udp.c
+++ b/drivers/net/ovpn/udp.c
@@ -344,6 +344,7 @@ void ovpn_udp_send_skb(struct ovpn_peer *peer, struct sock *sk,
 	int ret;
 
 	skb->dev = peer->ovpn->dev;
+	skb->mark = READ_ONCE(sk->sk_mark);
 	/* no checksum performed at this layer */
 	skb->ip_summed = CHECKSUM_NONE;
 
-- 
2.49.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net 2/3] ovpn: reject unexpected netlink attributes
  2025-07-16 11:54 [PATCH net 0/3] pull request: ovpn for net 2025-07-16 Antonio Quartulli
  2025-07-16 11:54 ` [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP Antonio Quartulli
@ 2025-07-16 11:54 ` Antonio Quartulli
  2025-07-16 11:54 ` [PATCH net 3/3] ovpn: reset GSO metadata after decapsulation Antonio Quartulli
  2 siblings, 0 replies; 7+ messages in thread
From: Antonio Quartulli @ 2025-07-16 11:54 UTC (permalink / raw)
  To: netdev
  Cc: Antonio Quartulli, Sabrina Dubroca, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Ralf Lici

Netlink ops do not expect all attributes to be always set, however
this condition is not explicitly coded any where, leading the user
to believe that all sent attributes are somewhat processed.

Fix this behaviour by introducing explicit checks.

For CMD_OVPN_PEER_GET and CMD_OVPN_KEY_GET directly open-code the
needed condition in the related ops handlers.
While for all other ops use attribute subsets in the ovpn.yaml spec file.

Fixes: b7a63391aa98 ("ovpn: add basic netlink support")
Reported-by: Ralf Lici <ralf@mandelbit.com>
Closes: https://github.com/OpenVPN/ovpn-net-next/issues/19
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 Documentation/netlink/specs/ovpn.yaml | 153 +++++++++++++++++++++++++-
 drivers/net/ovpn/netlink-gen.c        |  61 +++++++++-
 drivers/net/ovpn/netlink-gen.h        |   6 +
 drivers/net/ovpn/netlink.c            |  51 +++++++--
 4 files changed, 251 insertions(+), 20 deletions(-)

diff --git a/Documentation/netlink/specs/ovpn.yaml b/Documentation/netlink/specs/ovpn.yaml
index 096c51f0c69a..ba76426a542d 100644
--- a/Documentation/netlink/specs/ovpn.yaml
+++ b/Documentation/netlink/specs/ovpn.yaml
@@ -160,6 +160,66 @@ attribute-sets:
         name: link-tx-packets
         type: uint
         doc: Number of packets transmitted at the transport level
+  -
+    name: peer-new-input
+    subset-of: peer
+    attributes:
+      -
+        name: id
+      -
+        name: remote-ipv4
+      -
+        name: remote-ipv6
+      -
+        name: remote-ipv6-scope-id
+      -
+        name: remote-port
+      -
+        name: socket
+      -
+        name: vpn-ipv4
+      -
+        name: vpn-ipv6
+      -
+        name: local-ipv4
+      -
+        name: local-ipv6
+      -
+        name: keepalive-interval
+      -
+        name: keepalive-timeout
+  -
+    name: peer-set-input
+    subset-of: peer
+    attributes:
+      -
+        name: id
+      -
+        name: remote-ipv4
+      -
+        name: remote-ipv6
+      -
+        name: remote-ipv6-scope-id
+      -
+        name: remote-port
+      -
+        name: vpn-ipv4
+      -
+        name: vpn-ipv6
+      -
+        name: local-ipv4
+      -
+        name: local-ipv6
+      -
+        name: keepalive-interval
+      -
+        name: keepalive-timeout
+  -
+    name: peer-del-input
+    subset-of: peer
+    attributes:
+      -
+        name: id
   -
     name: keyconf
     attributes:
@@ -216,6 +276,33 @@ attribute-sets:
           obtain the actual cipher IV
         checks:
           exact-len: nonce-tail-size
+
+  -
+    name: keyconf-get
+    subset-of: keyconf
+    attributes:
+      -
+        name: peer-id
+      -
+        name: slot
+      -
+        name: key-id
+      -
+        name: cipher-alg
+  -
+    name: keyconf-swap-input
+    subset-of: keyconf
+    attributes:
+      -
+        name: peer-id
+  -
+    name: keyconf-del-input
+    subset-of: keyconf
+    attributes:
+      -
+        name: peer-id
+      -
+        name: slot
   -
     name: ovpn
     attributes:
@@ -235,12 +322,66 @@ attribute-sets:
         type: nest
         doc: Peer specific cipher configuration
         nested-attributes: keyconf
+  -
+    name: ovpn-peer-new-input
+    subset-of: ovpn
+    attributes:
+      -
+        name: ifindex
+      -
+        name: peer
+        nested-attributes: peer-new-input
+  -
+    name: ovpn-peer-set-input
+    subset-of: ovpn
+    attributes:
+      -
+        name: ifindex
+      -
+        name: peer
+        nested-attributes: peer-set-input
+  -
+    name: ovpn-peer-del-input
+    subset-of: ovpn
+    attributes:
+      -
+        name: ifindex
+      -
+        name: peer
+        nested-attributes: peer-del-input
+  -
+    name: ovpn-keyconf-get
+    subset-of: ovpn
+    attributes:
+      -
+        name: ifindex
+      -
+        name: keyconf
+        nested-attributes: keyconf-get
+  -
+    name: ovpn-keyconf-swap-input
+    subset-of: ovpn
+    attributes:
+      -
+        name: ifindex
+      -
+        name: keyconf
+        nested-attributes: keyconf-swap-input
+  -
+    name: ovpn-keyconf-del-input
+    subset-of: ovpn
+    attributes:
+      -
+        name: ifindex
+      -
+        name: keyconf
+        nested-attributes: keyconf-del-input
 
 operations:
   list:
     -
       name: peer-new
-      attribute-set: ovpn
+      attribute-set: ovpn-peer-new-input
       flags: [ admin-perm ]
       doc: Add a remote peer
       do:
@@ -252,7 +393,7 @@ operations:
             - peer
     -
       name: peer-set
-      attribute-set: ovpn
+      attribute-set: ovpn-peer-set-input
       flags: [ admin-perm ]
       doc: modify a remote peer
       do:
@@ -286,7 +427,7 @@ operations:
             - peer
     -
       name: peer-del
-      attribute-set: ovpn
+      attribute-set: ovpn-peer-del-input
       flags: [ admin-perm ]
       doc: Delete existing remote peer
       do:
@@ -316,7 +457,7 @@ operations:
             - keyconf
     -
       name: key-get
-      attribute-set: ovpn
+      attribute-set: ovpn-keyconf-get
       flags: [ admin-perm ]
       doc: Retrieve non-sensitive data about peer key and cipher
       do:
@@ -331,7 +472,7 @@ operations:
             - keyconf
     -
       name: key-swap
-      attribute-set: ovpn
+      attribute-set: ovpn-keyconf-swap-input
       flags: [ admin-perm ]
       doc: Swap primary and secondary session keys for a specific peer
       do:
@@ -350,7 +491,7 @@ operations:
       mcgrp: peers
     -
       name: key-del
-      attribute-set: ovpn
+      attribute-set: ovpn-keyconf-del-input
       flags: [ admin-perm ]
       doc: Delete cipher key for a specific peer
       do:
diff --git a/drivers/net/ovpn/netlink-gen.c b/drivers/net/ovpn/netlink-gen.c
index 58e1a4342378..14298188c5f1 100644
--- a/drivers/net/ovpn/netlink-gen.c
+++ b/drivers/net/ovpn/netlink-gen.c
@@ -29,6 +29,22 @@ const struct nla_policy ovpn_keyconf_nl_policy[OVPN_A_KEYCONF_DECRYPT_DIR + 1] =
 	[OVPN_A_KEYCONF_DECRYPT_DIR] = NLA_POLICY_NESTED(ovpn_keydir_nl_policy),
 };
 
+const struct nla_policy ovpn_keyconf_del_input_nl_policy[OVPN_A_KEYCONF_SLOT + 1] = {
+	[OVPN_A_KEYCONF_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_keyconf_peer_id_range),
+	[OVPN_A_KEYCONF_SLOT] = NLA_POLICY_MAX(NLA_U32, 1),
+};
+
+const struct nla_policy ovpn_keyconf_get_nl_policy[OVPN_A_KEYCONF_CIPHER_ALG + 1] = {
+	[OVPN_A_KEYCONF_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_keyconf_peer_id_range),
+	[OVPN_A_KEYCONF_SLOT] = NLA_POLICY_MAX(NLA_U32, 1),
+	[OVPN_A_KEYCONF_KEY_ID] = NLA_POLICY_MAX(NLA_U32, 7),
+	[OVPN_A_KEYCONF_CIPHER_ALG] = NLA_POLICY_MAX(NLA_U32, 2),
+};
+
+const struct nla_policy ovpn_keyconf_swap_input_nl_policy[OVPN_A_KEYCONF_PEER_ID + 1] = {
+	[OVPN_A_KEYCONF_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_keyconf_peer_id_range),
+};
+
 const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1] = {
 	[OVPN_A_KEYDIR_CIPHER_KEY] = NLA_POLICY_MAX_LEN(256),
 	[OVPN_A_KEYDIR_NONCE_TAIL] = NLA_POLICY_EXACT_LEN(OVPN_NONCE_TAIL_SIZE),
@@ -60,16 +76,49 @@ const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1] = {
 	[OVPN_A_PEER_LINK_TX_PACKETS] = { .type = NLA_UINT, },
 };
 
+const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1] = {
+	[OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range),
+};
+
+const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1] = {
+	[OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range),
+	[OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, },
+	[OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16),
+	[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID] = { .type = NLA_U32, },
+	[OVPN_A_PEER_REMOTE_PORT] = NLA_POLICY_MIN(NLA_BE16, 1),
+	[OVPN_A_PEER_SOCKET] = { .type = NLA_U32, },
+	[OVPN_A_PEER_VPN_IPV4] = { .type = NLA_BE32, },
+	[OVPN_A_PEER_VPN_IPV6] = NLA_POLICY_EXACT_LEN(16),
+	[OVPN_A_PEER_LOCAL_IPV4] = { .type = NLA_BE32, },
+	[OVPN_A_PEER_LOCAL_IPV6] = NLA_POLICY_EXACT_LEN(16),
+	[OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, },
+	[OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, },
+};
+
+const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1] = {
+	[OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range),
+	[OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, },
+	[OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16),
+	[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID] = { .type = NLA_U32, },
+	[OVPN_A_PEER_REMOTE_PORT] = NLA_POLICY_MIN(NLA_BE16, 1),
+	[OVPN_A_PEER_VPN_IPV4] = { .type = NLA_BE32, },
+	[OVPN_A_PEER_VPN_IPV6] = NLA_POLICY_EXACT_LEN(16),
+	[OVPN_A_PEER_LOCAL_IPV4] = { .type = NLA_BE32, },
+	[OVPN_A_PEER_LOCAL_IPV6] = NLA_POLICY_EXACT_LEN(16),
+	[OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, },
+	[OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, },
+};
+
 /* OVPN_CMD_PEER_NEW - do */
 static const struct nla_policy ovpn_peer_new_nl_policy[OVPN_A_PEER + 1] = {
 	[OVPN_A_IFINDEX] = { .type = NLA_U32, },
-	[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy),
+	[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_new_input_nl_policy),
 };
 
 /* OVPN_CMD_PEER_SET - do */
 static const struct nla_policy ovpn_peer_set_nl_policy[OVPN_A_PEER + 1] = {
 	[OVPN_A_IFINDEX] = { .type = NLA_U32, },
-	[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy),
+	[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_set_input_nl_policy),
 };
 
 /* OVPN_CMD_PEER_GET - do */
@@ -86,7 +135,7 @@ static const struct nla_policy ovpn_peer_get_dump_nl_policy[OVPN_A_IFINDEX + 1]
 /* OVPN_CMD_PEER_DEL - do */
 static const struct nla_policy ovpn_peer_del_nl_policy[OVPN_A_PEER + 1] = {
 	[OVPN_A_IFINDEX] = { .type = NLA_U32, },
-	[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_nl_policy),
+	[OVPN_A_PEER] = NLA_POLICY_NESTED(ovpn_peer_del_input_nl_policy),
 };
 
 /* OVPN_CMD_KEY_NEW - do */
@@ -98,19 +147,19 @@ static const struct nla_policy ovpn_key_new_nl_policy[OVPN_A_KEYCONF + 1] = {
 /* OVPN_CMD_KEY_GET - do */
 static const struct nla_policy ovpn_key_get_nl_policy[OVPN_A_KEYCONF + 1] = {
 	[OVPN_A_IFINDEX] = { .type = NLA_U32, },
-	[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy),
+	[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_get_nl_policy),
 };
 
 /* OVPN_CMD_KEY_SWAP - do */
 static const struct nla_policy ovpn_key_swap_nl_policy[OVPN_A_KEYCONF + 1] = {
 	[OVPN_A_IFINDEX] = { .type = NLA_U32, },
-	[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy),
+	[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_swap_input_nl_policy),
 };
 
 /* OVPN_CMD_KEY_DEL - do */
 static const struct nla_policy ovpn_key_del_nl_policy[OVPN_A_KEYCONF + 1] = {
 	[OVPN_A_IFINDEX] = { .type = NLA_U32, },
-	[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_nl_policy),
+	[OVPN_A_KEYCONF] = NLA_POLICY_NESTED(ovpn_keyconf_del_input_nl_policy),
 };
 
 /* Ops table for ovpn */
diff --git a/drivers/net/ovpn/netlink-gen.h b/drivers/net/ovpn/netlink-gen.h
index 66a4e4a0a055..220b5b2fdd4f 100644
--- a/drivers/net/ovpn/netlink-gen.h
+++ b/drivers/net/ovpn/netlink-gen.h
@@ -13,8 +13,14 @@
 
 /* Common nested types */
 extern const struct nla_policy ovpn_keyconf_nl_policy[OVPN_A_KEYCONF_DECRYPT_DIR + 1];
+extern const struct nla_policy ovpn_keyconf_del_input_nl_policy[OVPN_A_KEYCONF_SLOT + 1];
+extern const struct nla_policy ovpn_keyconf_get_nl_policy[OVPN_A_KEYCONF_CIPHER_ALG + 1];
+extern const struct nla_policy ovpn_keyconf_swap_input_nl_policy[OVPN_A_KEYCONF_PEER_ID + 1];
 extern const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1];
 extern const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1];
+extern const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1];
+extern const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1];
+extern const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1];
 
 int ovpn_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
 		     struct genl_info *info);
diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c
index a4ec53def46e..c7f382437630 100644
--- a/drivers/net/ovpn/netlink.c
+++ b/drivers/net/ovpn/netlink.c
@@ -352,7 +352,7 @@ int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 
 	ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
-			       ovpn_peer_nl_policy, info->extack);
+			       ovpn_peer_new_input_nl_policy, info->extack);
 	if (ret)
 		return ret;
 
@@ -476,7 +476,7 @@ int ovpn_nl_peer_set_doit(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 
 	ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
-			       ovpn_peer_nl_policy, info->extack);
+			       ovpn_peer_set_input_nl_policy, info->extack);
 	if (ret)
 		return ret;
 
@@ -654,7 +654,7 @@ int ovpn_nl_peer_get_doit(struct sk_buff *skb, struct genl_info *info)
 	struct ovpn_peer *peer;
 	struct sk_buff *msg;
 	u32 peer_id;
-	int ret;
+	int ret, i;
 
 	if (GENL_REQ_ATTR_CHECK(info, OVPN_A_PEER))
 		return -EINVAL;
@@ -668,6 +668,23 @@ int ovpn_nl_peer_get_doit(struct sk_buff *skb, struct genl_info *info)
 			      OVPN_A_PEER_ID))
 		return -EINVAL;
 
+	/* OVPN_CMD_PEER_GET expects only the PEER_ID, therefore
+	 * ensure that the user hasn't specified any other attribute.
+	 *
+	 * Unfortunately this check cannot be performed via netlink
+	 * spec/policy and must be open-coded.
+	 */
+	for (i = 0; i < OVPN_A_PEER_MAX + 1; i++) {
+		if (i == OVPN_A_PEER_ID)
+			continue;
+
+		if (attrs[i]) {
+			NL_SET_ERR_MSG_FMT_MOD(info->extack,
+					       "unexpected attribute %u", i);
+			return -EINVAL;
+		}
+	}
+
 	peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
 	peer = ovpn_peer_get_by_id(ovpn, peer_id);
 	if (!peer) {
@@ -768,7 +785,7 @@ int ovpn_nl_peer_del_doit(struct sk_buff *skb, struct genl_info *info)
 		return -EINVAL;
 
 	ret = nla_parse_nested(attrs, OVPN_A_PEER_MAX, info->attrs[OVPN_A_PEER],
-			       ovpn_peer_nl_policy, info->extack);
+			       ovpn_peer_del_input_nl_policy, info->extack);
 	if (ret)
 		return ret;
 
@@ -969,14 +986,14 @@ int ovpn_nl_key_get_doit(struct sk_buff *skb, struct genl_info *info)
 	struct ovpn_peer *peer;
 	struct sk_buff *msg;
 	u32 peer_id;
-	int ret;
+	int ret, i;
 
 	if (GENL_REQ_ATTR_CHECK(info, OVPN_A_KEYCONF))
 		return -EINVAL;
 
 	ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
 			       info->attrs[OVPN_A_KEYCONF],
-			       ovpn_keyconf_nl_policy, info->extack);
+			       ovpn_keyconf_get_nl_policy, info->extack);
 	if (ret)
 		return ret;
 
@@ -988,6 +1005,24 @@ int ovpn_nl_key_get_doit(struct sk_buff *skb, struct genl_info *info)
 			      OVPN_A_KEYCONF_SLOT))
 		return -EINVAL;
 
+	/* OVPN_CMD_KEY_GET expects only the PEER_ID and the SLOT, therefore
+	 * ensure that the user hasn't specified any other attribute.
+	 *
+	 * Unfortunately this check cannot be performed via netlink
+	 * spec/policy and must be open-coded.
+	 */
+	for (i = 0; i < OVPN_A_KEYCONF_MAX + 1; i++) {
+		if (i == OVPN_A_KEYCONF_PEER_ID ||
+		    i == OVPN_A_KEYCONF_SLOT)
+			continue;
+
+		if (attrs[i]) {
+			NL_SET_ERR_MSG_FMT_MOD(info->extack,
+					       "unexpected attribute %u", i);
+			return -EINVAL;
+		}
+	}
+
 	peer_id = nla_get_u32(attrs[OVPN_A_KEYCONF_PEER_ID]);
 	peer = ovpn_peer_get_by_id(ovpn, peer_id);
 	if (!peer) {
@@ -1037,7 +1072,7 @@ int ovpn_nl_key_swap_doit(struct sk_buff *skb, struct genl_info *info)
 
 	ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
 			       info->attrs[OVPN_A_KEYCONF],
-			       ovpn_keyconf_nl_policy, info->extack);
+			       ovpn_keyconf_swap_input_nl_policy, info->extack);
 	if (ret)
 		return ret;
 
@@ -1074,7 +1109,7 @@ int ovpn_nl_key_del_doit(struct sk_buff *skb, struct genl_info *info)
 
 	ret = nla_parse_nested(attrs, OVPN_A_KEYCONF_MAX,
 			       info->attrs[OVPN_A_KEYCONF],
-			       ovpn_keyconf_nl_policy, info->extack);
+			       ovpn_keyconf_del_input_nl_policy, info->extack);
 	if (ret)
 		return ret;
 
-- 
2.49.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH net 3/3] ovpn: reset GSO metadata after decapsulation
  2025-07-16 11:54 [PATCH net 0/3] pull request: ovpn for net 2025-07-16 Antonio Quartulli
  2025-07-16 11:54 ` [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP Antonio Quartulli
  2025-07-16 11:54 ` [PATCH net 2/3] ovpn: reject unexpected netlink attributes Antonio Quartulli
@ 2025-07-16 11:54 ` Antonio Quartulli
  2 siblings, 0 replies; 7+ messages in thread
From: Antonio Quartulli @ 2025-07-16 11:54 UTC (permalink / raw)
  To: netdev
  Cc: Ralf Lici, Sabrina Dubroca, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Gert Doering, Antonio Quartulli

From: Ralf Lici <ralf@mandelbit.com>

The ovpn_netdev_write() function is responsible for injecting
decapsulated and decrypted packets back into the local network stack.

Prior to this patch, the skb could retain GSO metadata from the outer,
encrypted tunnel packet. This original GSO metadata, relevant to the
sender's transport context, becomes invalid and misleading for the
tunnel/data path once the inner packet is exposed.

Leaving this stale metadata intact causes internal GSO validation checks
further down the kernel's network stack (validate_xmit_skb()) to fail,
leading to packet drops. The reasons for these failures vary by
protocol, for example:
- for ICMP, no offload handler is registered;
- for TCP and UDP, the respective offload handlers return errors when
  comparing skb->len to the outdated skb_shinfo(skb)->gso_size.

By calling skb_gso_reset(skb) we ensure the inner packet is presented to
gro_cells_receive() with a clean state, correctly indicating it is an
individual packet from the perspective of the local stack.

This change eliminates the "Driver has suspect GRO implementation, TCP
performance may be compromised" warning and improves overall TCP
performance by allowing GSO/GRO to function as intended on the
decapsulated traffic.

Fixes: 11851cbd60ea ("ovpn: implement TCP transport")
Reported-by: Gert Doering <gert@greenie.muc.de>
Closes: https://github.com/OpenVPN/ovpn-net-next/issues/4
Tested-by: Gert Doering <gert@greenie.muc.de>
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/io.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c
index ebf1e849506b..3e9e7f8444b3 100644
--- a/drivers/net/ovpn/io.c
+++ b/drivers/net/ovpn/io.c
@@ -62,6 +62,13 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
 	unsigned int pkt_len;
 	int ret;
 
+	/*
+	 * GSO state from the transport layer is not valid for the tunnel/data
+	 * path. Reset all GSO fields to prevent any further GSO processing
+	 * from entering an inconsistent state.
+	 */
+	skb_gso_reset(skb);
+
 	/* we can't guarantee the packet wasn't corrupted before entering the
 	 * VPN, therefore we give other layers a chance to check that
 	 */
-- 
2.49.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP
  2025-07-16 11:54 ` [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP Antonio Quartulli
@ 2025-07-17 14:50   ` patchwork-bot+netdevbpf
  0 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-07-17 14:50 UTC (permalink / raw)
  To: Antonio Quartulli; +Cc: netdev, ralf, sd, davem, edumazet, kuba, pabeni

Hello:

This series was applied to netdev/net.git (main)
by Antonio Quartulli <antonio@openvpn.net>:

On Wed, 16 Jul 2025 13:54:41 +0200 you wrote:
> From: Ralf Lici <ralf@mandelbit.com>
> 
> OpenVPN allows users to configure a FW mark on sockets used to
> communicate with other peers. The mark is set by means of the
> `SO_MARK` Linux socket option.
> 
> However, in the ovpn UDP code path, the socket's `sk_mark` value is
> currently ignored and it is not propagated to outgoing `skbs`.
> 
> [...]

Here is the summary with links:
  - [net,1/3] ovpn: propagate socket mark to skb in UDP
    https://git.kernel.org/netdev/net/c/4c88cfcc6738
  - [net,2/3] ovpn: reject unexpected netlink attributes
    https://git.kernel.org/netdev/net/c/af52020fc599
  - [net,3/3] ovpn: reset GSO metadata after decapsulation
    https://git.kernel.org/netdev/net/c/2022d704014d

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-07-17 14:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-16 11:54 [PATCH net 0/3] pull request: ovpn for net 2025-07-16 Antonio Quartulli
2025-07-16 11:54 ` [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP Antonio Quartulli
2025-07-17 14:50   ` patchwork-bot+netdevbpf
2025-07-16 11:54 ` [PATCH net 2/3] ovpn: reject unexpected netlink attributes Antonio Quartulli
2025-07-16 11:54 ` [PATCH net 3/3] ovpn: reset GSO metadata after decapsulation Antonio Quartulli
  -- strict thread matches above, loose matches on Subject: below --
2025-07-03 11:45 [PATCH net 0/3] pull request: ovpn for net 2025-07-03 Antonio Quartulli
2025-07-03 11:45 ` [PATCH net 1/3] ovpn: propagate socket mark to skb in UDP Antonio Quartulli
2025-07-03 14:02   ` Sabrina Dubroca

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).