72 lines
2.6 KiB
C
72 lines
2.6 KiB
C
// call_ring.c — статический кольцевой трейс вызовов (диагностика UAF в teardown)
|
|
#include "call_ring.h"
|
|
#include <stdio.h>
|
|
|
|
#if defined(_WIN32)
|
|
#include <io.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#endif
|
|
|
|
callring_entry_t g_callring[CALLRING_SIZE];
|
|
uint32_t g_callring_idx = 0;
|
|
|
|
static const char *cr_name(uint32_t code) {
|
|
switch (code) {
|
|
case CR_LINK_NEW: return "LINK_NEW";
|
|
case CR_LINK_CLOSE_IN: return "LINK_CLOSE_IN";
|
|
case CR_LINK_CLOSE_TCP: return "LINK_CLOSE_TCP";
|
|
case CR_LINK_CLOSE_FREE: return "LINK_CLOSE_FREE";
|
|
case CR_TCPCB_IN: return "TCPCB_IN";
|
|
case CR_TCPCB_FREE: return "TCPCB_FREE";
|
|
case CR_SRV_ONLINK: return "SRV_ONLINK";
|
|
case CR_SLINK_CLOSE: return "SLINK_CLOSE";
|
|
case CR_SLINK_IMPL: return "SLINK_IMPL";
|
|
case CR_SLINK_ONSTCP: return "SLINK_ONSTCP";
|
|
case CR_CONN_SETONCLOSE: return "CONN_SETONCLOSE";
|
|
case CR_CONN_DOCLOSE_IN: return "CONN_DOCLOSE_IN";
|
|
case CR_CONN_DOCLOSE_CB: return "CONN_DOCLOSE_CB";
|
|
case CR_CONN_FREE: return "CONN_FREE";
|
|
case CR_CCLOSE_IN: return "CCLOSE_IN";
|
|
case CR_CFREE_RES: return "CFREE_RES";
|
|
case CR_NCD_DEFER: return "NCD_DEFER";
|
|
default: return "?";
|
|
}
|
|
}
|
|
|
|
/* Дамп последних записей кольцевого буфера в /tmp/utun_callring.<pid> (и stderr
|
|
* при ошибке). Форматирование только через snprintf в стековый буфер — в
|
|
* обработчике сигнала не выделяет память. */
|
|
void callring_dump(void) {
|
|
char buf[192];
|
|
int fd = -1;
|
|
|
|
#if defined(_WIN32)
|
|
fd = 2;
|
|
#else
|
|
{
|
|
char path[96];
|
|
snprintf(path, sizeof(path), "/tmp/utun_callring.%d", (int)getpid());
|
|
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
}
|
|
if (fd < 0) fd = 2;
|
|
#endif
|
|
|
|
int n = snprintf(buf, sizeof(buf), "callring dump idx=%u\n", g_callring_idx);
|
|
if (n > 0) { ssize_t w = write(fd, buf, (size_t)n); (void)w; }
|
|
|
|
uint32_t total = g_callring_idx < CALLRING_SIZE ? g_callring_idx : CALLRING_SIZE;
|
|
uint32_t start = g_callring_idx >= CALLRING_SIZE ? g_callring_idx - CALLRING_SIZE : 0;
|
|
for (uint32_t k = 0; k < total; k++) {
|
|
const callring_entry_t *e = &g_callring[(start + k) % CALLRING_SIZE];
|
|
n = snprintf(buf, sizeof(buf), "%s a=0x%lx b=0x%lx\n", cr_name(e->code),
|
|
(unsigned long)e->a, (unsigned long)e->b);
|
|
if (n > 0) { ssize_t w = write(fd, buf, (size_t)n); (void)w; }
|
|
}
|
|
|
|
#if !defined(_WIN32)
|
|
if (fd != 2) close(fd);
|
|
#endif
|
|
}
|