Re: [PATCH net 1/2] socket: fix option SO_TIMESTAMPING_NEW

From: Willem de Bruijn
Date: Fri Oct 09 2020 - 20:26:41 EST


On Fri, Oct 9, 2020 at 6:32 AM Christian Eggers <ceggers@xxxxxxx> wrote:
>
> The comparison of optname with SO_TIMESTAMPING_NEW is wrong way around,
> so SOCK_TSTAMP_NEW will first be set and than reset again. Additionally
> move it out of the test for SOF_TIMESTAMPING_RX_SOFTWARE as this seems
> unrelated.
>
> This problem happens on 32 bit platforms were the libc has already
> switched to struct timespec64 (from SO_TIMExxx_OLD to SO_TIMExxx_NEW
> socket options). ptp4l complains with "missing timestamp on transmitted
> peer delay request" because the wrong format is received (and
> discarded).
>
> Fixes: 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW")
> Signed-off-by: Christian Eggers <ceggers@xxxxxxx>
> ---
> net/core/sock.c | 9 ++++-----
> 1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/net/core/sock.c b/net/core/sock.c
> index 34a8d12e38d7..3926804702c1 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -1024,16 +1024,15 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
> }
>
> sk->sk_tsflags = val;
> + if (optname != SO_TIMESTAMPING_NEW)
> + sock_reset_flag(sk, SOCK_TSTAMP_NEW);
> +
> if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
> sock_enable_timestamp(sk,
> SOCK_TIMESTAMPING_RX_SOFTWARE);
> - else {
> - if (optname == SO_TIMESTAMPING_NEW)
> - sock_reset_flag(sk, SOCK_TSTAMP_NEW);
> -

The idea is to select new vs old behavior depending on which of the
two setsockopts is called.

This suggested fix still sets and clears the flag if calling
SO_TIMESTAMPING_NEW to disable timestamping. Instead, how about

case SO_TIMESTAMPING_NEW:
- sock_set_flag(sk, SOCK_TSTAMP_NEW);
fallthrough;
case SO_TIMESTAMPING_OLD:
[..]
+ sock_valbool_flag(sk, SOCK_TSTAMP_NEW,
+ optname == SO_TIMESTAMPING_NEW);
+
if (val & SOF_TIMESTAMPING_OPT_ID &&

That is a subtle behavioral change, because it now leaves
SOCK_TSTAMP_NEW set also when timestamping is turned off. But this is
harmless, as in that case the versioning does not matter. A more
pedantic version would be

+ sock_valbool_flag(sk, SOCK_TSTAMP_NEW,
+ optname == SO_TIMESTAMPING_NEW &&
+ val & SOF_TIMESTAMPING_TX_RECORD_MASK);