From 8170a0c968f41dc8f29b7b52b714cae690267d51 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 17 Apr 2025 21:25:36 +0200 Subject: [PATCH 01/10] MAINTAINERS: add Sabrina as official reviewer for ovpn Sabrina put quite some effort in reviewing the ovpn module during its official submission to netdev. For this reason she obtain extensive knowledge of the module architecture and implementation. Make her an official reviewer, so that I can be supported in reviewing and acking new patches. Acked-by: Sabrina Dubroca Reviewed-by: Andrew Lunn Signed-off-by: Antonio Quartulli --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 800d23264c94..9019bcbcd50b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18199,6 +18199,7 @@ F: drivers/irqchip/irq-or1k-* OPENVPN DATA CHANNEL OFFLOAD M: Antonio Quartulli +R: Sabrina Dubroca L: openvpn-devel@lists.sourceforge.net (subscribers-only) L: netdev@vger.kernel.org S: Supported From 142e17cfb09ec0f1e8f09de25e81061b1b827da4 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 22 Apr 2025 22:52:35 +0200 Subject: [PATCH 02/10] MAINTAINERS: update git URL for ovpn Signed-off-by: Antonio Quartulli --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9019bcbcd50b..4b010ecc38f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18203,7 +18203,7 @@ R: Sabrina Dubroca L: openvpn-devel@lists.sourceforge.net (subscribers-only) L: netdev@vger.kernel.org S: Supported -T: git https://github.com/OpenVPN/linux-kernel-ovpn.git +T: git https://github.com/OpenVPN/ovpn-net-next.git F: Documentation/netlink/specs/ovpn.yaml F: drivers/net/ovpn/ F: include/uapi/linux/ovpn.h From 4e51141f1dce46189b347e59d008b7ca01044bf5 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 6 May 2025 01:05:01 +0200 Subject: [PATCH 03/10] ovpn: set skb->ignore_df = 1 before sending IPv6 packets out IPv6 user packets (sent over the tunnel) may be larger than the outgoing interface MTU after encapsulation. When this happens ovpn should allow the kernel to fragment them because they are "locally generated". To achieve the above, we must set skb->ignore_df = 1 so that ip6_fragment() can be made aware of this decision. Failing to do so will result in ip6_fragment() dropping the packet thinking it was "routed". No change is required in the IPv4 path, because when calling udp_tunnel_xmit_skb() we already pass the 'df' argument set to 0, therefore the resulting datagram is allowed to be fragmented if need be. Fixes: 08857b5ec5d9 ("ovpn: implement basic TX path (UDP)") Reported-by: Gert Doering Closes: https://github.com/OpenVPN/ovpn-net-next/issues/3 Tested-by: Gert Doering Acked-by: Gert Doering # as primary user Link: https://mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31577.html Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/udp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c index c9e189056f33..aef8c0406ec9 100644 --- a/drivers/net/ovpn/udp.c +++ b/drivers/net/ovpn/udp.c @@ -262,6 +262,16 @@ static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind, dst_cache_set_ip6(cache, dst, &fl.saddr); transmit: + /* user IPv6 packets may be larger than the transport interface + * MTU (after encapsulation), however, since they are locally + * generated we should ensure they get fragmented. + * Setting the ignore_df flag to 1 will instruct ip6_fragment() to + * fragment packets if needed. + * + * NOTE: this is not needed for IPv4 because we pass df=0 to + * udp_tunnel_xmit_skb() + */ + skb->ignore_df = 1; udp_tunnel6_xmit_skb(dst, sk, skb, skb->dev, &fl.saddr, &fl.daddr, 0, ip6_dst_hoplimit(dst), 0, fl.fl6_sport, fl.fl6_dport, udp_get_no_check6_tx(sk)); From 4ca6438da45688dae5c5958f640560f9496f21a4 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 7 May 2025 09:58:31 +0200 Subject: [PATCH 04/10] ovpn: don't drop skb's dst when xmitting packet When routing a packet to a LAN behind a peer, ovpn needs to inspect the route entry that brought the packet there in the first place. If this packet is truly routable, the route entry provides the GW to be used when looking up the VPN peer to send the packet to. However, the route entry is currently dropped before entering the ovpn xmit function, because the IFF_XMIT_DST_RELEASE priv_flag is enabled by default. Clear the IFF_XMIT_DST_RELEASE flag during interface setup to allow the route entry (skb's dst) to survive and thus be inspected by the ovpn routing logic. Fixes: a3aaef8cd173 ("ovpn: implement peer lookup logic") Reported-by: Gert Doering Closes: https://github.com/OpenVPN/ovpn-net-next/issues/2 Tested-by: Gert Doering Acked-by: Gert Doering # as a primary user Link: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31583.html Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/io.c | 2 ++ drivers/net/ovpn/main.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c index dd8a8055d967..7e4b89484c9d 100644 --- a/drivers/net/ovpn/io.c +++ b/drivers/net/ovpn/io.c @@ -398,6 +398,8 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev) netdev_name(ovpn->dev)); goto drop; } + /* dst was needed for peer selection - it can now be dropped */ + skb_dst_drop(skb); ovpn_peer_stats_increment_tx(&peer->vpn_stats, skb->len); ovpn_send(ovpn, skb_list.next, peer); diff --git a/drivers/net/ovpn/main.c b/drivers/net/ovpn/main.c index 0acb0934c1be..1bb1afe766a4 100644 --- a/drivers/net/ovpn/main.c +++ b/drivers/net/ovpn/main.c @@ -157,6 +157,11 @@ static void ovpn_setup(struct net_device *dev) dev->type = ARPHRD_NONE; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->priv_flags |= IFF_NO_QUEUE; + /* when routing packets to a LAN behind a client, we rely on the + * route entry that originally brought the packet into ovpn, so + * don't release it + */ + netif_keep_dst(dev); dev->lltx = true; dev->features |= feat; From 8624daf9f27dc9c58e266319b44d5c0f8d6a67df Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 6 May 2025 14:56:54 +0200 Subject: [PATCH 05/10] selftest/net/ovpn: fix crash in case of getaddrinfo() failure getaddrinfo() may fail with error code different from EAI_FAIL or EAI_NONAME, however in this case we still try to free the results object, thus leading to a crash. Fix this by bailing out on any possible error. Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module") Signed-off-by: Antonio Quartulli --- tools/testing/selftests/net/ovpn/ovpn-cli.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c index 69e41fc07fbc..c6372a1b4728 100644 --- a/tools/testing/selftests/net/ovpn/ovpn-cli.c +++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c @@ -1753,8 +1753,11 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, if (host) { ret = getaddrinfo(host, service, &hints, &result); - if (ret == EAI_NONAME || ret == EAI_FAIL) + if (ret) { + fprintf(stderr, "getaddrinfo on remote error: %s\n", + gai_strerror(ret)); return -1; + } if (!(result->ai_family == AF_INET && result->ai_addrlen == sizeof(struct sockaddr_in)) && @@ -1769,8 +1772,11 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, if (vpnip) { ret = getaddrinfo(vpnip, NULL, &hints, &result); - if (ret == EAI_NONAME || ret == EAI_FAIL) + if (ret) { + fprintf(stderr, "getaddrinfo on vpnip error: %s\n", + gai_strerror(ret)); return -1; + } if (!(result->ai_family == AF_INET && result->ai_addrlen == sizeof(struct sockaddr_in)) && From 47e8e9d29eaae43abbb2e1ac202545249792f6f2 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 7 May 2025 14:26:30 +0200 Subject: [PATCH 06/10] ovpn: fix ndo_start_xmit return value on error ndo_start_xmit is basically expected to always return NETDEV_TX_OK. However, in case of error, it was currently returning NET_XMIT_DROP, which is not a valid netdev_tx_t return value, leading to misinterpretation. Change ndo_start_xmit to always return NETDEV_TX_OK to signal back to the caller that the packet was handled (even if dropped). Effects of this bug can be seen when sending IPv6 packets having no peer to forward them to: $ ip netns exec ovpn-server oping -c20 fd00:abcd:220:201::1 PING fd00:abcd:220:201::1 (fd00:abcd:220:201::1) 56 bytes of data.00:abcd:220:201 :1 ping_send failed: No buffer space available ping_sendto: No buffer space available ping_send failed: No buffer space available ping_sendto: No buffer space available ... Fixes: c2d950c4672a ("ovpn: add basic interface creation/destruction/management routines") Reported-by: Gert Doering Closes: https://github.com/OpenVPN/ovpn-net-next/issues/5 Tested-by: Gert Doering Acked-by: Gert Doering Link: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31591.html Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c index 7e4b89484c9d..43f428ac112e 100644 --- a/drivers/net/ovpn/io.c +++ b/drivers/net/ovpn/io.c @@ -410,7 +410,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev) dev_dstats_tx_dropped(ovpn->dev); skb_tx_error(skb); kfree_skb_list(skb); - return NET_XMIT_DROP; + return NETDEV_TX_OK; } /** From 944f8b6abab6a456254cf9617131144adac1a506 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 6 May 2025 15:01:00 +0200 Subject: [PATCH 07/10] selftest/net/ovpn: extend coverage with more test cases To increase code coverage, extend the ovpn selftests with the following cases: * connect UDP peers using a mix of IPv6 and IPv4 at the transport layer * run full test with tunnel MTU equal to transport MTU (exercising IP layer fragmentation) * ping "LAN IP" served by VPN peer ("LAN behind a client" test case) Signed-off-by: Antonio Quartulli --- tools/testing/selftests/net/ovpn/Makefile | 1 + tools/testing/selftests/net/ovpn/common.sh | 18 +++++++++++++++++- tools/testing/selftests/net/ovpn/ovpn-cli.c | 9 +++++---- tools/testing/selftests/net/ovpn/test.sh | 6 +++++- tools/testing/selftests/net/ovpn/udp_peers.txt | 11 ++++++----- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/tools/testing/selftests/net/ovpn/Makefile b/tools/testing/selftests/net/ovpn/Makefile index 2d102878cb6d..e0926d76b4c8 100644 --- a/tools/testing/selftests/net/ovpn/Makefile +++ b/tools/testing/selftests/net/ovpn/Makefile @@ -20,6 +20,7 @@ LDLIBS += $(VAR_LDLIBS) TEST_FILES = common.sh TEST_PROGS = test.sh \ + test-large-mtu.sh \ test-chachapoly.sh \ test-tcp.sh \ test-float.sh \ diff --git a/tools/testing/selftests/net/ovpn/common.sh b/tools/testing/selftests/net/ovpn/common.sh index 7502292a1ee0..88869c675d03 100644 --- a/tools/testing/selftests/net/ovpn/common.sh +++ b/tools/testing/selftests/net/ovpn/common.sh @@ -11,6 +11,8 @@ ALG=${ALG:-aes} PROTO=${PROTO:-UDP} FLOAT=${FLOAT:-0} +LAN_IP="11.11.11.11" + create_ns() { ip netns add peer${1} } @@ -24,15 +26,25 @@ setup_ns() { ip link add veth${p} netns peer0 type veth peer name veth${p} netns peer${p} ip -n peer0 addr add 10.10.${p}.1/24 dev veth${p} + ip -n peer0 addr add fd00:0:0:${p}::1/64 dev veth${p} ip -n peer0 link set veth${p} up ip -n peer${p} addr add 10.10.${p}.2/24 dev veth${p} + ip -n peer${p} addr add fd00:0:0:${p}::2/64 dev veth${p} ip -n peer${p} link set veth${p} up done fi ip netns exec peer${1} ${OVPN_CLI} new_iface tun${1} $MODE ip -n peer${1} addr add ${2} dev tun${1} + # add a secondary IP to peer 1, to test a LAN behind a client + if [ ${1} -eq 1 -a -n "${LAN_IP}" ]; then + ip -n peer${1} addr add ${LAN_IP} dev tun${1} + ip -n peer0 route add ${LAN_IP} via $(echo ${2} |sed -e s'!/.*!!') dev tun0 + fi + if [ -n "${3}" ]; then + ip -n peer${1} link set mtu ${3} dev tun${1} + fi ip -n peer${1} link set tun${1} up } @@ -46,7 +58,11 @@ add_peer() { data64.key done else - ip netns exec peer${1} ${OVPN_CLI} new_peer tun${1} ${1} 1 10.10.${1}.1 1 + RADDR=$(awk "NR == ${1} {print \$2}" ${UDP_PEERS_FILE}) + RPORT=$(awk "NR == ${1} {print \$3}" ${UDP_PEERS_FILE}) + LPORT=$(awk "NR == ${1} {print \$5}" ${UDP_PEERS_FILE}) + ip netns exec peer${1} ${OVPN_CLI} new_peer tun${1} ${1} ${LPORT} \ + ${RADDR} ${RPORT} ip netns exec peer${1} ${OVPN_CLI} new_key tun${1} ${1} 1 0 ${ALG} 1 \ data64.key fi diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c index c6372a1b4728..de9c26f98b2e 100644 --- a/tools/testing/selftests/net/ovpn/ovpn-cli.c +++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c @@ -1934,7 +1934,8 @@ static void ovpn_waitbg(void) static int ovpn_run_cmd(struct ovpn_ctx *ovpn) { - char peer_id[10], vpnip[INET6_ADDRSTRLEN], raddr[128], rport[10]; + char peer_id[10], vpnip[INET6_ADDRSTRLEN], laddr[128], lport[10]; + char raddr[128], rport[10]; int n, ret; FILE *fp; @@ -2050,8 +2051,8 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn) return -1; } - while ((n = fscanf(fp, "%s %s %s %s\n", peer_id, raddr, rport, - vpnip)) == 4) { + while ((n = fscanf(fp, "%s %s %s %s %s %s\n", peer_id, laddr, + lport, raddr, rport, vpnip)) == 6) { struct ovpn_ctx peer_ctx = { 0 }; peer_ctx.ifindex = ovpn->ifindex; @@ -2355,7 +2356,7 @@ int main(int argc, char *argv[]) } memset(&ovpn, 0, sizeof(ovpn)); - ovpn.sa_family = AF_INET; + ovpn.sa_family = AF_UNSPEC; ovpn.cipher = OVPN_CIPHER_ALG_NONE; ovpn.cmd = ovpn_parse_cmd(argv[1]); diff --git a/tools/testing/selftests/net/ovpn/test.sh b/tools/testing/selftests/net/ovpn/test.sh index 7b62897b0240..e8acdc303307 100755 --- a/tools/testing/selftests/net/ovpn/test.sh +++ b/tools/testing/selftests/net/ovpn/test.sh @@ -18,7 +18,7 @@ for p in $(seq 0 ${NUM_PEERS}); do done for p in $(seq 0 ${NUM_PEERS}); do - setup_ns ${p} 5.5.5.$((${p} + 1))/24 + setup_ns ${p} 5.5.5.$((${p} + 1))/24 ${MTU} done for p in $(seq 0 ${NUM_PEERS}); do @@ -34,8 +34,12 @@ sleep 1 for p in $(seq 1 ${NUM_PEERS}); do ip netns exec peer0 ping -qfc 500 -w 3 5.5.5.$((${p} + 1)) + ip netns exec peer0 ping -qfc 500 -s 3000 -w 3 5.5.5.$((${p} + 1)) done +# ping LAN behind client 1 +ip netns exec peer0 ping -qfc 500 -w 3 ${LAN_IP} + if [ "$FLOAT" == "1" ]; then # make clients float.. for p in $(seq 1 ${NUM_PEERS}); do diff --git a/tools/testing/selftests/net/ovpn/udp_peers.txt b/tools/testing/selftests/net/ovpn/udp_peers.txt index 32f14bd9347a..e9773ddf875c 100644 --- a/tools/testing/selftests/net/ovpn/udp_peers.txt +++ b/tools/testing/selftests/net/ovpn/udp_peers.txt @@ -1,5 +1,6 @@ -1 10.10.1.2 1 5.5.5.2 -2 10.10.2.2 1 5.5.5.3 -3 10.10.3.2 1 5.5.5.4 -4 10.10.4.2 1 5.5.5.5 -5 10.10.5.2 1 5.5.5.6 +1 10.10.1.1 1 10.10.1.2 1 5.5.5.2 +2 10.10.2.1 1 10.10.2.2 1 5.5.5.3 +3 10.10.3.1 1 10.10.3.2 1 5.5.5.4 +4 fd00:0:0:4::1 1 fd00:0:0:4::2 1 5.5.5.5 +5 fd00:0:0:5::1 1 fd00:0:0:5::2 1 5.5.5.6 +6 fd00:0:0:6::1 1 fd00:0:0:6::2 1 5.5.5.7 From adcdaac57d3ccb38f2f1b0a8da31b5c1403385f0 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 30 Apr 2025 02:35:18 +0200 Subject: [PATCH 08/10] ovpn: drop useless reg_state check in keepalive worker The keepalive worker is cancelled before calling unregister_netdevice_queue(), therefore it will never hit a situation where the reg_state can be different than NETDEV_REGISTERED. For this reason, checking reg_state is useless and the condition can be removed. Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/peer.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c index a37f89fffb02..24eb9d81429e 100644 --- a/drivers/net/ovpn/peer.c +++ b/drivers/net/ovpn/peer.c @@ -1353,8 +1353,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work) } /* prevent rearming if the interface is being destroyed */ - if (next_run > 0 && - READ_ONCE(ovpn->dev->reg_state) == NETREG_REGISTERED) { + if (next_run > 0) { netdev_dbg(ovpn->dev, "scheduling keepalive work: now=%llu next_run=%llu delta=%llu\n", next_run, now, next_run - now); From 0ca74dfabdfe9c6274b11554adc46b79d6f44955 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Fri, 9 May 2025 15:32:13 +0200 Subject: [PATCH 09/10] ovpn: improve 'no route to host' debug message When debugging a 'no route to host' error it can be beneficial to know the address of the unreachable destination. Print it along the debugging text. While at it, add a missing parenthesis in a different debugging message inside ovpn_peer_endpoints_update(). Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/io.c | 14 ++++++++++++-- drivers/net/ovpn/peer.c | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c index 43f428ac112e..10d8afecec55 100644 --- a/drivers/net/ovpn/io.c +++ b/drivers/net/ovpn/io.c @@ -394,8 +394,18 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev) /* retrieve peer serving the destination IP of this packet */ peer = ovpn_peer_get_by_dst(ovpn, skb); if (unlikely(!peer)) { - net_dbg_ratelimited("%s: no peer to send data to\n", - netdev_name(ovpn->dev)); + switch (skb->protocol) { + case htons(ETH_P_IP): + net_dbg_ratelimited("%s: no peer to send data to dst=%pI4\n", + netdev_name(ovpn->dev), + &ip_hdr(skb)->daddr); + break; + case htons(ETH_P_IPV6): + net_dbg_ratelimited("%s: no peer to send data to dst=%pI6c\n", + netdev_name(ovpn->dev), + &ipv6_hdr(skb)->daddr); + break; + } goto drop; } /* dst was needed for peer selection - it can now be dropped */ diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c index 24eb9d81429e..a1fd27b9c038 100644 --- a/drivers/net/ovpn/peer.c +++ b/drivers/net/ovpn/peer.c @@ -258,7 +258,7 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb) */ if (unlikely(!ipv6_addr_equal(&bind->local.ipv6, &ipv6_hdr(skb)->daddr))) { - net_dbg_ratelimited("%s: learning local IPv6 for peer %d (%pI6c -> %pI6c\n", + net_dbg_ratelimited("%s: learning local IPv6 for peer %d (%pI6c -> %pI6c)\n", netdev_name(peer->ovpn->dev), peer->id, &bind->local.ipv6, &ipv6_hdr(skb)->daddr); From 40d48527a587b5c2bd4b7ba00974732a93052cae Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 13 May 2025 01:17:22 +0200 Subject: [PATCH 10/10] ovpn: fix check for skb_to_sgvec_nomark() return value Depending on the data offset, skb_to_sgvec_nomark() may use less scatterlist elements than what was forecasted by the previous call to skb_cow_data(). It specifically happens when 'skbheadlen(skb) < offset', because in this case we entirely skip the skb's head, which would have required its own scatterlist element. For this reason, it doesn't make sense to check that skb_to_sgvec_nomark() returns the same value as skb_cow_data(), but we can rather check for errors only, as it happens in other parts of the kernel. Signed-off-by: Antonio Quartulli --- drivers/net/ovpn/crypto_aead.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/ovpn/crypto_aead.c b/drivers/net/ovpn/crypto_aead.c index 74ee639ac868..2cca759feffa 100644 --- a/drivers/net/ovpn/crypto_aead.c +++ b/drivers/net/ovpn/crypto_aead.c @@ -88,12 +88,15 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks, /* build scatterlist to encrypt packet payload */ ret = skb_to_sgvec_nomark(skb, sg + 1, 0, skb->len); - if (unlikely(nfrags != ret)) - return -EINVAL; + if (unlikely(ret < 0)) { + netdev_err(peer->ovpn->dev, + "encrypt: cannot map skb to sg: %d\n", ret); + return ret; + } /* append auth_tag onto scatterlist */ __skb_push(skb, tag_size); - sg_set_buf(sg + nfrags + 1, skb->data, tag_size); + sg_set_buf(sg + ret + 1, skb->data, tag_size); /* obtain packet ID, which is used both as a first * 4 bytes of nonce and last 4 bytes of associated data. @@ -201,11 +204,14 @@ int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks, /* build scatterlist to decrypt packet payload */ ret = skb_to_sgvec_nomark(skb, sg + 1, payload_offset, payload_len); - if (unlikely(nfrags != ret)) - return -EINVAL; + if (unlikely(ret < 0)) { + netdev_err(peer->ovpn->dev, + "decrypt: cannot map skb to sg: %d\n", ret); + return ret; + } /* append auth_tag onto scatterlist */ - sg_set_buf(sg + nfrags + 1, skb->data + OVPN_AAD_SIZE, tag_size); + sg_set_buf(sg + ret + 1, skb->data + OVPN_AAD_SIZE, tag_size); /* iv may be required by async crypto */ ovpn_skb_cb(skb)->iv = kmalloc(OVPN_NONCE_SIZE, GFP_ATOMIC);