ip6_datagram_send_ctl() parses both SOL_IPV6 and SOL_SOCKET control messages. For SOL_SOCKET messages it passes ipc6->sockc to __sock_cmsg_send(), which updates fields such as tsflags with read-modify-write operations. The IPV6_2292PKTOPTIONS and flowlabel option paths only set ipc6.opt before calling ip6_datagram_send_ctl(). If a SOL_SOCKET control message such as SO_TIMESTAMPING_* or SCM_TS_OPT_ID is present, this can read uninitialized sockc state. Initialize the ipcm6_cookie with ipcm6_init_sk(), as the normal IPv6 sendmsg paths do, before overriding ->opt with the temporary option buffer. Signed-off-by: Wayen Yan --- net/ipv6/ip6_flowlabel.c | 1 + net/ipv6/ipv6_sockglue.c | 1 + 2 files changed, 2 insertions(+) diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 1ab5ad0dcf24..5cbfb82710f4 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -405,6 +405,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, msg.msg_control = (void *)(fl->opt+1); memset(&flowi6, 0, sizeof(flowi6)); + ipcm6_init_sk(&ipc6, sk); ipc6.opt = fl->opt; err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, &ipc6); if (err) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index b4c977434c2e..0dcd2c224014 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -839,6 +839,7 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int optname, msg.msg_controllen = optlen; msg.msg_control_is_user = false; msg.msg_control = (void *)(opt+1); + ipcm6_init_sk(&ipc6, sk); ipc6.opt = opt; retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, &ipc6); -- 2.51.0