mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 04:04:31 +02:00
Merge branch 'contrib/github_pr_14196_v5.2' into 'release/v5.2'
fix(esp_http_server): prevent concurrent access to socket used in async http requests (GitHub PR) (v5.2) See merge request espressif/esp-idf!34685
This commit is contained in:
@@ -247,6 +247,11 @@ static int httpd_process_session(struct sock_db *session, void *context)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// session is busy in an async task, do not process here.
|
||||||
|
if (session->for_async_req) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
process_session_context_t *ctx = (process_session_context_t *)context;
|
process_session_context_t *ctx = (process_session_context_t *)context;
|
||||||
int fd = session->fd;
|
int fd = session->fd;
|
||||||
|
|
||||||
|
@@ -72,6 +72,7 @@ static int enum_function(struct sock_db *session, void *context)
|
|||||||
case HTTPD_TASK_INIT:
|
case HTTPD_TASK_INIT:
|
||||||
session->fd = -1;
|
session->fd = -1;
|
||||||
session->ctx = NULL;
|
session->ctx = NULL;
|
||||||
|
session->for_async_req = false;
|
||||||
break;
|
break;
|
||||||
// Get active session
|
// Get active session
|
||||||
case HTTPD_TASK_GET_ACTIVE:
|
case HTTPD_TASK_GET_ACTIVE:
|
||||||
@@ -87,7 +88,7 @@ static int enum_function(struct sock_db *session, void *context)
|
|||||||
break;
|
break;
|
||||||
// Set descriptor
|
// Set descriptor
|
||||||
case HTTPD_TASK_SET_DESCRIPTOR:
|
case HTTPD_TASK_SET_DESCRIPTOR:
|
||||||
if (session->fd != -1) {
|
if (session->fd != -1 && !session->for_async_req) {
|
||||||
FD_SET(session->fd, ctx->fdset);
|
FD_SET(session->fd, ctx->fdset);
|
||||||
if (session->fd > ctx->max_fd) {
|
if (session->fd > ctx->max_fd) {
|
||||||
ctx->max_fd = session->fd;
|
ctx->max_fd = session->fd;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -392,54 +392,54 @@ esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_code_t error, const ch
|
|||||||
const char *status;
|
const char *status;
|
||||||
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case HTTPD_501_METHOD_NOT_IMPLEMENTED:
|
case HTTPD_501_METHOD_NOT_IMPLEMENTED:
|
||||||
status = "501 Method Not Implemented";
|
status = "501 Method Not Implemented";
|
||||||
msg = "Server does not support this method";
|
msg = "Server does not support this method";
|
||||||
break;
|
break;
|
||||||
case HTTPD_505_VERSION_NOT_SUPPORTED:
|
case HTTPD_505_VERSION_NOT_SUPPORTED:
|
||||||
status = "505 Version Not Supported";
|
status = "505 Version Not Supported";
|
||||||
msg = "HTTP version not supported by server";
|
msg = "HTTP version not supported by server";
|
||||||
break;
|
break;
|
||||||
case HTTPD_400_BAD_REQUEST:
|
case HTTPD_400_BAD_REQUEST:
|
||||||
status = "400 Bad Request";
|
status = "400 Bad Request";
|
||||||
msg = "Bad request syntax";
|
msg = "Bad request syntax";
|
||||||
break;
|
break;
|
||||||
case HTTPD_401_UNAUTHORIZED:
|
case HTTPD_401_UNAUTHORIZED:
|
||||||
status = "401 Unauthorized";
|
status = "401 Unauthorized";
|
||||||
msg = "No permission -- see authorization schemes";
|
msg = "No permission -- see authorization schemes";
|
||||||
break;
|
break;
|
||||||
case HTTPD_403_FORBIDDEN:
|
case HTTPD_403_FORBIDDEN:
|
||||||
status = "403 Forbidden";
|
status = "403 Forbidden";
|
||||||
msg = "Request forbidden -- authorization will not help";
|
msg = "Request forbidden -- authorization will not help";
|
||||||
break;
|
break;
|
||||||
case HTTPD_404_NOT_FOUND:
|
case HTTPD_404_NOT_FOUND:
|
||||||
status = "404 Not Found";
|
status = "404 Not Found";
|
||||||
msg = "Nothing matches the given URI";
|
msg = "Nothing matches the given URI";
|
||||||
break;
|
break;
|
||||||
case HTTPD_405_METHOD_NOT_ALLOWED:
|
case HTTPD_405_METHOD_NOT_ALLOWED:
|
||||||
status = "405 Method Not Allowed";
|
status = "405 Method Not Allowed";
|
||||||
msg = "Specified method is invalid for this resource";
|
msg = "Specified method is invalid for this resource";
|
||||||
break;
|
break;
|
||||||
case HTTPD_408_REQ_TIMEOUT:
|
case HTTPD_408_REQ_TIMEOUT:
|
||||||
status = "408 Request Timeout";
|
status = "408 Request Timeout";
|
||||||
msg = "Server closed this connection";
|
msg = "Server closed this connection";
|
||||||
break;
|
break;
|
||||||
case HTTPD_414_URI_TOO_LONG:
|
case HTTPD_414_URI_TOO_LONG:
|
||||||
status = "414 URI Too Long";
|
status = "414 URI Too Long";
|
||||||
msg = "URI is too long";
|
msg = "URI is too long";
|
||||||
break;
|
break;
|
||||||
case HTTPD_411_LENGTH_REQUIRED:
|
case HTTPD_411_LENGTH_REQUIRED:
|
||||||
status = "411 Length Required";
|
status = "411 Length Required";
|
||||||
msg = "Client must specify Content-Length";
|
msg = "Client must specify Content-Length";
|
||||||
break;
|
break;
|
||||||
case HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE:
|
case HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE:
|
||||||
status = "431 Request Header Fields Too Large";
|
status = "431 Request Header Fields Too Large";
|
||||||
msg = "Header fields are too long";
|
msg = "Header fields are too long";
|
||||||
break;
|
break;
|
||||||
case HTTPD_500_INTERNAL_SERVER_ERROR:
|
case HTTPD_500_INTERNAL_SERVER_ERROR:
|
||||||
default:
|
default:
|
||||||
status = "500 Internal Server Error";
|
status = "500 Internal Server Error";
|
||||||
msg = "Server has encountered an unexpected error";
|
msg = "Server has encountered an unexpected error";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If user has provided custom message, override default message */
|
/* If user has provided custom message, override default message */
|
||||||
@@ -575,9 +575,24 @@ esp_err_t httpd_req_async_handler_begin(httpd_req_t *r, httpd_req_t **out)
|
|||||||
}
|
}
|
||||||
memcpy(async->aux, r->aux, sizeof(struct httpd_req_aux));
|
memcpy(async->aux, r->aux, sizeof(struct httpd_req_aux));
|
||||||
|
|
||||||
|
// Copy response header block
|
||||||
|
struct httpd_data *hd = (struct httpd_data *) r->handle;
|
||||||
|
struct httpd_req_aux *async_aux = (struct httpd_req_aux *) async->aux;
|
||||||
|
struct httpd_req_aux *r_aux = (struct httpd_req_aux *) r->aux;
|
||||||
|
|
||||||
|
async_aux->resp_hdrs = calloc(hd->config.max_resp_headers, sizeof(struct resp_hdr));
|
||||||
|
if (async_aux->resp_hdrs == NULL) {
|
||||||
|
free(async_aux);
|
||||||
|
free(async);
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
memcpy(async_aux->resp_hdrs, r_aux->resp_hdrs, hd->config.max_resp_headers * sizeof(struct resp_hdr));
|
||||||
|
|
||||||
|
// Prevent the main thread from reading the rest of the request after the handler returns.
|
||||||
|
r_aux->remaining_len = 0;
|
||||||
|
|
||||||
// mark socket as "in use"
|
// mark socket as "in use"
|
||||||
struct httpd_req_aux *ra = r->aux;
|
r_aux->sd->for_async_req = true;
|
||||||
ra->sd->for_async_req = true;
|
|
||||||
|
|
||||||
*out = async;
|
*out = async;
|
||||||
|
|
||||||
@@ -593,6 +608,7 @@ esp_err_t httpd_req_async_handler_complete(httpd_req_t *r)
|
|||||||
struct httpd_req_aux *ra = r->aux;
|
struct httpd_req_aux *ra = r->aux;
|
||||||
ra->sd->for_async_req = false;
|
ra->sd->for_async_req = false;
|
||||||
|
|
||||||
|
free(ra->resp_hdrs);
|
||||||
free(r->aux);
|
free(r->aux);
|
||||||
free(r);
|
free(r);
|
||||||
|
|
||||||
@@ -619,7 +635,7 @@ static int httpd_sock_err(const char *ctx, int sockfd)
|
|||||||
int errval;
|
int errval;
|
||||||
ESP_LOGW(TAG, LOG_FMT("error in %s : %d"), ctx, errno);
|
ESP_LOGW(TAG, LOG_FMT("error in %s : %d"), ctx, errno);
|
||||||
|
|
||||||
switch(errno) {
|
switch (errno) {
|
||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
case EINTR:
|
case EINTR:
|
||||||
errval = HTTPD_SOCK_ERR_TIMEOUT;
|
errval = HTTPD_SOCK_ERR_TIMEOUT;
|
||||||
|
Reference in New Issue
Block a user