From: Antonio Quartulli <antonio@openvpn.net>
To: Sabrina Dubroca <sd@queasysnail.net>
Cc: netdev@vger.kernel.org, Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Donald Hunter <donald.hunter@gmail.com>,
Shuah Khan <shuah@kernel.org>,
ryazanov.s.a@gmail.com, Andrew Lunn <andrew+netdev@lunn.ch>,
Simon Horman <horms@kernel.org>,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
Xiao Liang <shaw.leon@gmail.com>,
David Ahern <dsahern@kernel.org>
Subject: Re: [PATCH net-next v20 12/25] ovpn: implement TCP transport
Date: Mon, 3 Mar 2025 16:48:25 +0100 [thread overview]
Message-ID: <c5c4e113-e86c-42ef-861b-3a6bc9d8ad19@openvpn.net> (raw)
In-Reply-To: <Z8XF06vDCNreOL4E@hog>
On 03/03/2025 16:08, Sabrina Dubroca wrote:
> 2025-02-27, 02:21:37 +0100, Antonio Quartulli wrote:
>> @@ -94,11 +96,23 @@ void ovpn_socket_release(struct ovpn_peer *peer)
>> * detached before it can be picked by a concurrent reader.
>> */
>> lock_sock(sock->sock->sk);
>> - ovpn_socket_put(peer, sock);
>> + released = ovpn_socket_put(peer, sock);
>> release_sock(sock->sock->sk);
>>
>> /* align all readers with sk_user_data being NULL */
>> synchronize_rcu();
>> +
>> + /* following cleanup should happen with lock released */
>> + if (released) {
>> + if (sock->sock->sk->sk_protocol == IPPROTO_UDP) {
>> + netdev_put(sock->ovpn->dev, &sock->dev_tracker);
>> + } else if (sock->sock->sk->sk_protocol == IPPROTO_TCP) {
>> + /* wait for TCP jobs to terminate */
>> + ovpn_tcp_socket_wait_finish(sock);
>> + ovpn_peer_put(sock->peer);
>> + }
>> + kfree_rcu(sock, rcu);
>
> kfree_rcu after synchronize_rcu is a bit unexpected. Do we still need
> to wait before we free sock, now that we have synchronize_rcu before?
Ah good point. Waiting one RCU period is what kfree_rcu() is there for,
hence we could just call kfree() at this point.
>
>> + }
>> }
>>
>
>
>
>> +static int ovpn_tcp_parse(struct strparser *strp, struct sk_buff *skb)
>> +{
>> + struct strp_msg *rxm = strp_msg(skb);
>> + __be16 blen;
>> + u16 len;
>> + int err;
>> +
>> + /* when packets are written to the TCP stream, they are prepended with
>> + * two bytes indicating the actual packet size.
>> + * Here we read those two bytes and move the skb data pointer to the
>> + * beginning of the packet
>
> There's no update to skb->data being done in ovpn_tcp_parse AFAICT.
I concur :)
>
> [...]
>> +static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
>> +{
>> + struct ovpn_peer *peer = container_of(strp, struct ovpn_peer, tcp.strp);
>> + struct strp_msg *msg = strp_msg(skb);
>> + size_t pkt_len = msg->full_len - 2;
>> + size_t off = msg->offset + 2;
>> + u8 opcode;
>> +
>> + /* ensure skb->data points to the beginning of the openvpn packet */
>> + if (!pskb_pull(skb, off)) {
>
> Is that the one you mean in the previous comment?
Yes. The comment was probably placed there in a previous
version/prototype and never moved.
I'll fix that.
>
>> + net_warn_ratelimited("%s: packet too small for peer %u\n",
>> + netdev_name(peer->ovpn->dev), peer->id);
>> + goto err;
>> + }
> [some checks]
>> + /* DATA_V2 packets are handled in kernel, the rest goes to user space */
>> + opcode = ovpn_opcode_from_skb(skb, 0);
>> + if (unlikely(opcode != OVPN_DATA_V2)) {
>> + if (opcode == OVPN_DATA_V1) {
>> + net_warn_ratelimited("%s: DATA_V1 detected on the TCP stream\n",
>> + netdev_name(peer->ovpn->dev));
>> + goto err;
>
> In TCP encap, receiving OVPN_DATA_V1 packets is going to kill the peer:
>
>> +err:
>> + dev_core_stats_rx_dropped_inc(peer->ovpn->dev);
>> + kfree_skb(skb);
>> + ovpn_peer_del(peer, OVPN_DEL_PEER_REASON_TRANSPORT_ERROR);
>> +}
>> +
>
> but that's not the case with the UDP encap (ovpn_udp_encap_recv simply
> drops those packets). Should the TCP/UDP behavior be consistent?
Ideally a UDP DATA_V1 could be just a replayed/spoofed packet, so
killing the peer doesn't sound good. It'd be a very easy attack.
Doing the same in TCP is much much harder (if practical at all) and in
that case it'd be impossible to understand what's happening on the
stream, so we just abort.
I think any TCP connection (without TCP-MD5) that gets messed up this
way will abort.
>
>
>
>
>> +void ovpn_tcp_send_skb(struct ovpn_peer *peer, struct socket *sock,
>> + struct sk_buff *skb)
>> +{
>> + u16 len = skb->len;
>> +
>> + *(__be16 *)__skb_push(skb, sizeof(u16)) = htons(len);
>> +
>> + spin_lock_nested(&sock->sk->sk_lock.slock, OVPN_TCP_DEPTH_NESTING);
>
> With this, lockdep is still going to complain in the unlikely case
> that ovpn-TCP traffic is carried over another ovpn-TCP socket, right?
> (probably fine to leave it like that)
Yeah.
I am not sure how much complexity we'd need to workaround that.
I also assume it's fine to keep it this way (this is also what L2TP does).
>
>
> [...]
>> +static int ovpn_tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
>> +{
>> + struct ovpn_socket *sock;
>> + int ret, linear = PAGE_SIZE;
>> + struct ovpn_peer *peer;
>> + struct sk_buff *skb;
>> +
>> + lock_sock(sk);
>> + rcu_read_lock();
>> + sock = rcu_dereference_sk_user_data(sk);
>> + if (unlikely(!sock || !sock->peer || !ovpn_peer_hold(sock->peer))) {
>> + rcu_read_unlock();
>> + release_sock(sk);
>> + return -EIO;
>> + }
>> + rcu_read_unlock();
>> + peer = sock->peer;
>
> This used to be done under RCU in previous versions of the series. Why
> is it after rcu_read_unlock now? (likely safe since we're under
> lock_sock so detach can't happen)
Yeah, while restructuring I assumed it could be taken out of the RCU
read section and so I kept it out.
>
>> +
>> + if (msg->msg_flags & ~MSG_DONTWAIT) {
>> + ret = -EOPNOTSUPP;
>> + goto peer_free;
>> + }
>
>
--
Antonio Quartulli
OpenVPN Inc.
next prev parent reply other threads:[~2025-03-03 15:48 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-27 1:21 [PATCH net-next v20 00/25] Introducing OpenVPN Data Channel Offload Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 01/25] mailmap: remove unwanted entry for Antonio Quartulli Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 02/25] net: introduce OpenVPN Data Channel Offload (ovpn) Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 03/25] ovpn: add basic netlink support Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 04/25] ovpn: add basic interface creation/destruction/management routines Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 05/25] ovpn: keep carrier always on for MP interfaces Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 06/25] ovpn: introduce the ovpn_peer object Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 07/25] ovpn: introduce the ovpn_socket object Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 08/25] ovpn: implement basic TX path (UDP) Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 09/25] ovpn: implement basic RX " Antonio Quartulli
2025-02-28 15:25 ` Sabrina Dubroca
2025-03-03 14:47 ` Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 10/25] ovpn: implement packet processing Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 11/25] ovpn: store tunnel and transport statistics Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 12/25] ovpn: implement TCP transport Antonio Quartulli
2025-03-02 18:59 ` Sabrina Dubroca
2025-03-02 20:59 ` Antonio Quartulli
2025-03-03 15:08 ` Sabrina Dubroca
2025-03-03 15:48 ` Antonio Quartulli [this message]
2025-02-27 1:21 ` [PATCH net-next v20 13/25] skb: implement skb_send_sock_locked_with_flags() Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 14/25] ovpn: add support for MSG_NOSIGNAL in tcp_sendmsg Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 15/25] ovpn: implement multi-peer support Antonio Quartulli
2025-03-03 13:08 ` Sabrina Dubroca
2025-03-03 14:45 ` Antonio Quartulli
2025-03-03 15:38 ` Sabrina Dubroca
2025-02-27 1:21 ` [PATCH net-next v20 16/25] ovpn: implement peer lookup logic Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 17/25] ovpn: implement keepalive mechanism Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 18/25] ovpn: add support for updating local UDP endpoint Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 19/25] ovpn: add support for peer floating Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 20/25] ovpn: implement peer add/get/dump/delete via netlink Antonio Quartulli
2025-03-02 18:24 ` Sabrina Dubroca
2025-03-02 21:00 ` Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 21/25] ovpn: implement key add/get/del/swap " Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 22/25] ovpn: kill key and notify userspace in case of IV exhaustion Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 23/25] ovpn: notify userspace when a peer is deleted Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 24/25] ovpn: add basic ethtool support Antonio Quartulli
2025-02-27 1:21 ` [PATCH net-next v20 25/25] testing/selftests: add test tool and scripts for ovpn module Antonio Quartulli
2025-02-27 16:21 ` [PATCH net-next v20 00/25] Introducing OpenVPN Data Channel Offload Jakub Kicinski
2025-02-28 14:21 ` Antonio Quartulli
2025-02-28 1:40 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c5c4e113-e86c-42ef-861b-3a6bc9d8ad19@openvpn.net \
--to=antonio@openvpn.net \
--cc=andrew+netdev@lunn.ch \
--cc=donald.hunter@gmail.com \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=ryazanov.s.a@gmail.com \
--cc=sd@queasysnail.net \
--cc=shaw.leon@gmail.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox