Commit ff73f834 authored by Kees Cook's avatar Kees Cook Committed by Jakub Kicinski
Browse files

sock: Use unsafe_memcpy() for sock_copy()



While testing for places where zero-sized destinations were still showing
up in the kernel, sock_copy() and inet_reqsk_clone() were found, which
are using very specific memcpy() offsets for both avoiding a portion of
struct sock, and copying beyond the end of it (since struct sock is really
just a common header before the protocol-specific allocation). Instead
of trying to unravel this historical lack of container_of(), just switch
to unsafe_memcpy(), since that's effectively what was happening already
(memcpy() wasn't checking 0-sized destinations while the code base was
being converted away from fake flexible arrays).

Avoid the following false positive warning with future changes to
CONFIG_FORTIFY_SOURCE:

  memcpy: detected field-spanning write (size 3068) of destination "&nsk->__sk_common.skc_dontcopy_end" at net/core/sock.c:2057 (size 0)

Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20240304212928.make.772-kees@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 4166204d
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -2053,8 +2053,9 @@ static void sock_copy(struct sock *nsk, const struct sock *osk)

	memcpy(nsk, osk, offsetof(struct sock, sk_dontcopy_begin));

	memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end,
	       prot->obj_size - offsetof(struct sock, sk_dontcopy_end));
	unsafe_memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end,
		      prot->obj_size - offsetof(struct sock, sk_dontcopy_end),
		      /* alloc is larger than struct, see sk_prot_alloc() */);

#ifdef CONFIG_SECURITY_NETWORK
	nsk->sk_security = sptr;
+3 −2
Original line number Diff line number Diff line
@@ -906,8 +906,9 @@ static struct request_sock *inet_reqsk_clone(struct request_sock *req,

	memcpy(nreq_sk, req_sk,
	       offsetof(struct sock, sk_dontcopy_begin));
	memcpy(&nreq_sk->sk_dontcopy_end, &req_sk->sk_dontcopy_end,
	       req->rsk_ops->obj_size - offsetof(struct sock, sk_dontcopy_end));
	unsafe_memcpy(&nreq_sk->sk_dontcopy_end, &req_sk->sk_dontcopy_end,
		      req->rsk_ops->obj_size - offsetof(struct sock, sk_dontcopy_end),
		      /* alloc is larger than struct, see above */);

	sk_node_init(&nreq_sk->sk_node);
	nreq_sk->sk_tx_queue_mapping = req_sk->sk_tx_queue_mapping;