Browse Source

uasync: снапшот полей socket_node в poll()/select() — защита от realloc во время коллбэков (UAF)

v2
evgeny 3 weeks ago
parent
commit
836c715299
  1. 80
      lib/u_async.c

80
lib/u_async.c

@ -1158,11 +1158,22 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) {
struct socket_node* node = &ua->sockets->sockets[idx];
if (!node->active) continue;
/* Снапшот полей — коллбэки могут реаллоцировать ua->sockets (node станет висячим) */
int local_fd = node->fd;
socket_t local_sock = node->sock;
int local_type = node->type;
void* local_ud = node->user_data;
socket_callback_t local_except = node->except_cbk;
socket_callback_t local_read = node->read_cbk;
socket_callback_t local_write = node->write_cbk;
socket_t_callback_t local_read_sock = node->read_cbk_sock;
socket_t_callback_t local_write_sock = node->write_cbk_sock;
SOCKET s;
if (node->type == SOCKET_NODE_TYPE_SOCK) {
s = node->sock;
if (local_type == SOCKET_NODE_TYPE_SOCK) {
s = local_sock;
} else {
s = (SOCKET)node->fd;
s = (SOCKET)local_fd;
}
int has_read = FD_ISSET(s, &read_fds);
@ -1173,31 +1184,31 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) {
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "select→fd=%d r=%d w=%d e=%d", (int)s, has_read, has_write, has_except);
if (has_except) {
if (node->except_cbk) {
node->except_cbk(node->fd, node->user_data);
if (local_except) {
local_except(local_fd, local_ud);
}
}
if (has_read) {
if (node->type == SOCKET_NODE_TYPE_SOCK) {
if (node->read_cbk_sock) {
node->read_cbk_sock(node->sock, node->user_data);
if (local_type == SOCKET_NODE_TYPE_SOCK) {
if (local_read_sock) {
local_read_sock(local_sock, local_ud);
}
} else {
if (node->read_cbk) {
node->read_cbk(node->fd, node->user_data);
if (local_read) {
local_read(local_fd, local_ud);
}
}
}
if (has_write) {
if (node->type == SOCKET_NODE_TYPE_SOCK) {
if (node->write_cbk_sock) {
node->write_cbk_sock(node->sock, node->user_data);
if (local_type == SOCKET_NODE_TYPE_SOCK) {
if (local_write_sock) {
local_write_sock(local_sock, local_ud);
}
} else {
if (node->write_cbk) {
node->write_cbk(node->fd, node->user_data);
if (local_write) {
local_write(local_fd, local_ud);
}
}
}
@ -1250,28 +1261,39 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) {
}
if (!node) continue; // Socket may have been removed
/* Снапшот полей — коллбэки могут реаллоцировать ua->sockets (node станет висячим) */
int local_fd = node->fd;
socket_t local_sock = node->sock;
int local_type = node->type;
void* local_ud = node->user_data;
socket_callback_t local_except = node->except_cbk;
socket_callback_t local_read = node->read_cbk;
socket_callback_t local_write = node->write_cbk;
socket_t_callback_t local_read_sock = node->read_cbk_sock;
socket_t_callback_t local_write_sock = node->write_cbk_sock;
/* Read readiness BEFORE error — avoid losing data on combined IN+ERR/HUP events */
if (ua->poll_fds[i].revents & POLLIN) {
if (node->type == SOCKET_NODE_TYPE_SOCK) {
if (node->read_cbk_sock) {
node->read_cbk_sock(node->sock, node->user_data);
if (local_type == SOCKET_NODE_TYPE_SOCK) {
if (local_read_sock) {
local_read_sock(local_sock, local_ud);
}
} else {
if (node->read_cbk) {
node->read_cbk(node->fd, node->user_data);
if (local_read) {
local_read(local_fd, local_ud);
}
}
}
/* Write readiness BEFORE error — flush pending writes before handling HUP */
if (ua->poll_fds[i].revents & POLLOUT) {
if (node->type == SOCKET_NODE_TYPE_SOCK) {
if (node->write_cbk_sock) {
node->write_cbk_sock(node->sock, node->user_data);
if (local_type == SOCKET_NODE_TYPE_SOCK) {
if (local_write_sock) {
local_write_sock(local_sock, local_ud);
}
} else {
if (node->write_cbk) {
node->write_cbk(node->fd, node->user_data);
if (local_write) {
local_write(local_fd, local_ud);
}
}
}
@ -1279,15 +1301,15 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) {
/* Check for error conditions LAST — I/O handlers drain/process data first */
if (ua->poll_fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) {
/* Treat as exceptional condition */
if (node->except_cbk) {
node->except_cbk(node->fd, node->user_data);
if (local_except) {
local_except(local_fd, local_ud);
}
}
/* Exceptional data (out-of-band) */
if (ua->poll_fds[i].revents & POLLPRI) {
if (node->except_cbk) {
node->except_cbk(node->fd, node->user_data);
if (local_except) {
local_except(local_fd, local_ud);
}
}
}

Loading…
Cancel
Save