Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tcp: Sanitize CMSG flags and reserved args in tcp_zerocopy_receive.

Explicitly define reserved field and require it and any subsequent
fields to be zero-valued for now. Additionally, limit the valid CMSG
flags that tcp_zerocopy_receive accepts.

Fixes: 7eeba1706eba ("tcp: Add receive timestamp support for receive zerocopy.")
Signed-off-by: Arjun Roy <arjunroy@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
Suggested-by: David Ahern <dsahern@gmail.com>
Suggested-by: Leon Romanovsky <leon@kernel.org>
Suggested-by: Jakub Kicinski <kuba@kernel.org>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arjun Roy and committed by
David S. Miller
3c5a2fd0 9fbb4a7a

+11 -2
+1 -1
include/uapi/linux/tcp.h
··· 357 357 __u64 msg_control; /* ancillary data */ 358 358 __u64 msg_controllen; 359 359 __u32 msg_flags; 360 - /* __u32 hole; Next we must add >1 u32 otherwise length checks fail. */ 360 + __u32 reserved; /* set to 0 for now */ 361 361 }; 362 362 #endif /* _UAPI_LINUX_TCP_H */
+10 -1
net/ipv4/tcp.c
··· 2030 2030 err); 2031 2031 } 2032 2032 2033 + #define TCP_VALID_ZC_MSG_FLAGS (TCP_CMSG_TS) 2033 2034 static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk, 2034 2035 struct scm_timestamping_internal *tss); 2035 2036 static void tcp_zc_finalize_rx_tstamp(struct sock *sk, ··· 4153 4152 return -EFAULT; 4154 4153 if (len < offsetofend(struct tcp_zerocopy_receive, length)) 4155 4154 return -EINVAL; 4156 - if (len > sizeof(zc)) { 4155 + if (unlikely(len > sizeof(zc))) { 4156 + err = check_zeroed_user(optval + sizeof(zc), 4157 + len - sizeof(zc)); 4158 + if (err < 1) 4159 + return err == 0 ? -EINVAL : err; 4157 4160 len = sizeof(zc); 4158 4161 if (put_user(len, optlen)) 4159 4162 return -EFAULT; 4160 4163 } 4161 4164 if (copy_from_user(&zc, optval, len)) 4162 4165 return -EFAULT; 4166 + if (zc.reserved) 4167 + return -EINVAL; 4168 + if (zc.msg_flags & ~(TCP_VALID_ZC_MSG_FLAGS)) 4169 + return -EINVAL; 4163 4170 lock_sock(sk); 4164 4171 err = tcp_zerocopy_receive(sk, &zc, &tss); 4165 4172 release_sock(sk);