From: Ralf Lici 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 Link: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31877.html Signed-off-by: Antonio Quartulli --- 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 The OVPN_A_PEER_LOCAL_PORT is designed to be a read-only attribute that ovpn sends back to userspace to show the local port being used to talk to that specific peer. However, we forgot to reject it when parsing CMD_PEER_NEW/SET messages. This is not a critical issue because the incoming value is just ignored, but it may fool userspace which expects some change in behaviour. Explicitly error out and send back a message if OVPN_A_PEER_LOCAL_PORT is specified in a CMD_PEER_NEW/SET message. Reported-by: Ralf Lici Closes: https://github.com/OpenVPN/ovpn-net-next/issues/19 Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/netlink.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/ovpn/netlink.c b/drivers/net/ovpn/netlink.c index a4ec53def46e..17d23d01c6d8 100644 --- a/drivers/net/ovpn/netlink.c +++ b/drivers/net/ovpn/netlink.c @@ -224,6 +224,17 @@ static int ovpn_nl_peer_precheck(struct ovpn_priv *ovpn, return -EINVAL; } + /* the local port cannot be set by userspace because the socket + * being passed is already bound to one. + * OVPN_A_PEER_LOCAL_PORT is for sending peer status only (check + * ovpn_nl_send_peer()) + */ + if (attrs[OVPN_A_PEER_LOCAL_PORT]) { + NL_SET_ERR_MSG_MOD(info->extack, + "cannot specify local port (socket is bound already)"); + return -EINVAL; + } + /* check that local and remote address families are the same even * after parsing v4mapped IPv6 addresses. * (if addresses are not provided, family will be AF_UNSPEC and -- 2.49.0 From: Ralf Lici 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 Closes: https://github.com/OpenVPN/ovpn-net-next/issues/4 Tested-by: Gert Doering Signed-off-by: Ralf Lici Signed-off-by: Antonio Quartulli --- 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.0