cf-socket: error if address can't be copied

- When converting Curl_addrinfo to Curl_sockaddr_ex, if the address
  length is too large then return error CURLE_TOO_LARGE.

Prior to this change the address structure was truncated on copy, and
the length shortened which I think is incorrect.

AFAICS the only time it could conceivably happen is when a UNIX socket
path is too long, and even then curl should've accounted for that by
having a structure that is large enough to store it. This is why I added
a DEBUGASSERT for debug builds, because I don't think it should ever
happen.

Closes https://github.com/curl/curl/pull/15784
This commit is contained in:
Jay Satiro 2024-12-19 17:12:02 -05:00
parent b7be4011c6
commit 55367416f5
3 changed files with 56 additions and 20 deletions

View File

@ -306,9 +306,9 @@ tcpkeepalive(struct Curl_easy *data,
* Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport)
CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport)
{
/*
* The Curl_sockaddr_ex structure is basically libcurl's external API
@ -334,9 +334,13 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
}
dest->addrlen = (unsigned int)ai->ai_addrlen;
if(dest->addrlen > sizeof(struct Curl_sockaddr_storage))
dest->addrlen = sizeof(struct Curl_sockaddr_storage);
if(dest->addrlen > sizeof(struct Curl_sockaddr_storage)) {
DEBUGASSERT(0);
return CURLE_TOO_LARGE;
}
memcpy(&dest->curl_sa_addr, ai->ai_addr, dest->addrlen);
return CURLE_OK;
}
static CURLcode socket_open(struct Curl_easy *data,
@ -395,12 +399,16 @@ CURLcode Curl_socket_open(struct Curl_easy *data,
curl_socket_t *sockfd)
{
struct Curl_sockaddr_ex dummy;
CURLcode result;
if(!addr)
/* if the caller does not want info back, use a local temp copy */
addr = &dummy;
Curl_sock_assign_addr(addr, ai, transport);
result = Curl_sock_assign_addr(addr, ai, transport);
if(result)
return result;
return socket_open(data, addr, sockfd);
}
@ -959,14 +967,20 @@ struct cf_socket_ctx {
BIT(active);
};
static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
const struct Curl_addrinfo *ai,
int transport)
static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx,
const struct Curl_addrinfo *ai,
int transport)
{
CURLcode result;
memset(ctx, 0, sizeof(*ctx));
ctx->sock = CURL_SOCKET_BAD;
ctx->transport = transport;
Curl_sock_assign_addr(&ctx->addr, ai, transport);
result = Curl_sock_assign_addr(&ctx->addr, ai, transport);
if(result)
return result;
#ifdef DEBUGBUILD
{
char *p = getenv("CURL_DBG_SOCK_WBLOCK");
@ -995,6 +1009,8 @@ static void cf_socket_ctx_init(struct cf_socket_ctx *ctx,
}
}
#endif
return result;
}
static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
@ -1805,7 +1821,10 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
cf_socket_ctx_init(ctx, ai, transport);
result = cf_socket_ctx_init(ctx, ai, transport);
if(result)
goto out;
result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx);
@ -1954,7 +1973,10 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
cf_socket_ctx_init(ctx, ai, transport);
result = cf_socket_ctx_init(ctx, ai, transport);
if(result)
goto out;
result = Curl_cf_create(&cf, &Curl_cft_udp, ctx);
@ -2006,7 +2028,10 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
cf_socket_ctx_init(ctx, ai, transport);
result = cf_socket_ctx_init(ctx, ai, transport);
if(result)
goto out;
result = Curl_cf_create(&cf, &Curl_cft_unix, ctx);

View File

@ -95,9 +95,9 @@ void Curl_sndbuf_init(curl_socket_t sockfd);
* Assign the address `ai` to the Curl_sockaddr_ex `dest` and
* set the transport used.
*/
void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport);
CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest,
const struct Curl_addrinfo *ai,
int transport);
/**
* Creates a cfilter that opens a TCP socket to the given address

View File

@ -132,15 +132,23 @@ struct cf_msh3_ctx {
static void h3_stream_hash_free(void *stream);
static void cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
const struct Curl_addrinfo *ai)
static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
const struct Curl_addrinfo *ai)
{
CURLcode result;
DEBUGASSERT(!ctx->initialized);
Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
result = Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
if(result)
return result;
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
ctx->initialized = TRUE;
return result;
}
static void cf_msh3_ctx_free(struct cf_msh3_ctx *ctx)
@ -1087,7 +1095,10 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf,
result = CURLE_OUT_OF_MEMORY;
goto out;
}
cf_msh3_ctx_init(ctx, ai);
result = cf_msh3_ctx_init(ctx, ai);
if(result)
goto out;
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);