lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <2a90f702-3061-46b6-aafa-cf8c1ba3d0de@openvpn.net>
Date: Thu, 14 Nov 2024 09:12:01 +0100
From: Antonio Quartulli <antonio@...nvpn.net>
To: Sabrina Dubroca <sd@...asysnail.net>
Cc: Eric Dumazet <edumazet@...gle.com>, Jakub Kicinski <kuba@...nel.org>,
 Paolo Abeni <pabeni@...hat.com>, Donald Hunter <donald.hunter@...il.com>,
 Shuah Khan <shuah@...nel.org>, ryazanov.s.a@...il.com,
 Andrew Lunn <andrew@...n.ch>, netdev@...r.kernel.org,
 linux-kernel@...r.kernel.org, linux-kselftest@...r.kernel.org
Subject: Re: [PATCH net-next v11 15/23] ovpn: implement keepalive mechanism

On 13/11/2024 11:36, Sabrina Dubroca wrote:
> 2024-11-12, 14:20:45 +0100, Antonio Quartulli wrote:
>> On 05/11/2024 19:10, Sabrina Dubroca wrote:
>>> 2024-10-29, 11:47:28 +0100, Antonio Quartulli wrote:
>>>> @@ -105,6 +132,9 @@ void ovpn_decrypt_post(void *data, int ret)
>>>>    		goto drop;
>>>>    	}
>>>> +	/* keep track of last received authenticated packet for keepalive */
>>>> +	peer->last_recv = ktime_get_real_seconds();
>>>
>>> It doesn't look like we're locking the peer here so that should be a
>>> WRITE_ONCE() (and READ_ONCE(peer->last_recv) for all reads).
>>
>> Is that because last_recv is 64 bit long (and might be more than one word on
>> certain architectures)?
>>
>> I don't remember having to do so for reading/writing 32 bit long integers.
> 
> AFAIK it's not just that. The compiler is free to do the read/write in
> any way it wants when you don't specify _ONCE. On the read side, it
> could read from memory a single time or multiple times (getting
> possibly different values each time), or maybe split the load
> (possibly reading chunks from different values being written in
> parallel).

Ok, thanks. Will switch to WRITE/READ_ONE then.

> 
>> I presume we need a WRITE_ONCE also upon initialization in
>> ovpn_peer_keepalive_set() right?
>> We still want to coordinate that with other reads/writes.
> 
> I think it makes sense, yes.

ACK

[...]
> 
>>>> +	/* check for peer timeout */
>>>> +	expired = false;
>>>> +	timeout = peer->keepalive_timeout;
>>>> +	delta = now - peer->last_recv;
>>>
>>> I'm not sure that's always > 0 if we finish decrypting a packet just
>>> as the workqueue starts:
>>>
>>>     ovpn_peer_keepalive_work
>>>       now = ...
>>>
>>>                                          ovpn_decrypt_post
>>>                                            peer->last_recv = ...
>>>
>>>     ovpn_peer_keepalive_work_single
>>>       delta: now < peer->last_recv
>>>
>>
>> Yeah, there is nothing preventing this from happening...but is this truly a
>> problem? The math should still work, no?
> 
> We'll fail "delta < timeout" (which we shouldn't), so we'll end up
> either in the "expired = true" case, or not updating
> keepalive_recv_exp. Both of these seem not ideal.

delta is signed, so it'll end up being a negative value and "delta < 
timeout" should not fail then. Unless I am missing something.

Anyway, this was just an exercise to understand what was going on.
I already changed the code as per your suggestion (the fact that we are 
still discussing this chunk proves that it needed to be simplified :))

> 
>>
>> However:
>>
>>>
>>>
>>>> +	if (delta < timeout) {
>>>> +		peer->keepalive_recv_exp = now + timeout - delta;
>>>
>>> I'd shorten that to
>>>
>>>       peer->keepalive_recv_exp = peer->last_recv + timeout;
>>>
>>> it's a bit more readable to my eyes and avoids risks of wrapping
>>> values.
>>>
>>> So I'd probably get rid of delta and go with:
>>>
>>>       last_recv = READ_ONCE(peer->last_recv)
>>>       if (now < last_recv + timeout) {
>>>       	peer->keepalive_recv_exp = last_recv + timeout;
>>>       	next_run1 = peer->keepalive_recv_exp;
>>>       } else if ...
>>>
>>>> +		next_run1 = peer->keepalive_recv_exp;
>>>> +	} else if (peer->keepalive_recv_exp > now) {
>>>> +		next_run1 = peer->keepalive_recv_exp;
>>>> +	} else {
>>>> +		expired = true;
>>>> +	}
>>
>> I agree this is simpler to read and gets rid of some extra operations.
>>
>> [note: I took inspiration from nat_keepalive_work_single() - it could be
>> simplified as well I guess]
> 
> Ah, ok. I wanted to review this code when it was posted but didn't
> have time :(

It can still be fixed ;)


Thanks.
Regards,

-- 
Antonio Quartulli
OpenVPN Inc.


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ