mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-05-10 19:00:57 +08:00
fix: deadlock in whisper, use-after-free in callbacks, log rotation, tail parsing
- Whisper: copy target client ref out of room lock before calling client_send, preventing lock-ordering inversion deadlock - Channel callbacks: call ssh_remove_channel_callbacks before releasing refs to prevent use-after-free if a callback fires during cleanup - Log rotation: rotate messages.log to messages.log.1 when it exceeds 10 MiB, preventing unbounded growth on public servers - tail -nN: accept both "tail -n5" and "tail -n 5" forms, matching standard Unix tail behavior Closes #36
This commit is contained in:
parent
e319c7aa42
commit
b1c1e5a894
3 changed files with 30 additions and 7 deletions
|
|
@ -22,6 +22,7 @@
|
||||||
#define MAX_EXEC_COMMAND_LEN 1024
|
#define MAX_EXEC_COMMAND_LEN 1024
|
||||||
#define MAX_CLIENTS 64
|
#define MAX_CLIENTS 64
|
||||||
#define LOG_FILE "messages.log"
|
#define LOG_FILE "messages.log"
|
||||||
|
#define MAX_LOG_SIZE (10 * 1024 * 1024) /* 10 MiB */
|
||||||
#define HOST_KEY_FILE "host_key"
|
#define HOST_KEY_FILE "host_key"
|
||||||
#define TNT_DEFAULT_STATE_DIR "."
|
#define TNT_DEFAULT_STATE_DIR "."
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,16 @@ int message_save(const message_t *msg) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Rotate if the log exceeds MAX_LOG_SIZE */
|
||||||
|
long file_size = ftell(fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
if (file_size > MAX_LOG_SIZE) {
|
||||||
|
char backup_path[PATH_MAX + 4];
|
||||||
|
snprintf(backup_path, sizeof(backup_path), "%s.1", log_path);
|
||||||
|
rename(log_path, backup_path);
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&g_message_file_lock);
|
pthread_mutex_unlock(&g_message_file_lock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -895,7 +895,7 @@ static int parse_tail_count(const char *args, int *count) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(args, "-n", 2) == 0 && isspace((unsigned char)args[2])) {
|
if (strncmp(args, "-n", 2) == 0) {
|
||||||
args += 2;
|
args += 2;
|
||||||
while (*args && isspace((unsigned char)*args)) {
|
while (*args && isspace((unsigned char)*args)) {
|
||||||
args++;
|
args++;
|
||||||
|
|
@ -1171,21 +1171,28 @@ static void execute_command(client_t *client) {
|
||||||
" w <username> <message>\n");
|
" w <username> <message>\n");
|
||||||
} else {
|
} else {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
client_t *target = NULL;
|
||||||
pthread_rwlock_rdlock(&g_room->lock);
|
pthread_rwlock_rdlock(&g_room->lock);
|
||||||
for (int i = 0; i < g_room->client_count; i++) {
|
for (int i = 0; i < g_room->client_count; i++) {
|
||||||
if (strcmp(g_room->clients[i]->username, target_name) == 0) {
|
if (strcmp(g_room->clients[i]->username, target_name) == 0) {
|
||||||
char whisper[MAX_MESSAGE_LEN];
|
target = g_room->clients[i];
|
||||||
snprintf(whisper, sizeof(whisper),
|
client_addref(target);
|
||||||
"\r\n\033[35m[whisper from %s]: %s\033[0m\r\n",
|
|
||||||
client->username, rest);
|
|
||||||
client_send(g_room->clients[i], whisper, strlen(whisper));
|
|
||||||
g_room->clients[i]->redraw_pending = true;
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_rwlock_unlock(&g_room->lock);
|
pthread_rwlock_unlock(&g_room->lock);
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
char whisper[MAX_MESSAGE_LEN];
|
||||||
|
snprintf(whisper, sizeof(whisper),
|
||||||
|
"\r\n\033[35m[whisper from %s]: %s\033[0m\r\n",
|
||||||
|
client->username, rest);
|
||||||
|
client_send(target, whisper, strlen(whisper));
|
||||||
|
target->redraw_pending = true;
|
||||||
|
client_release(target);
|
||||||
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
buffer_appendf(output, sizeof(output), &pos,
|
buffer_appendf(output, sizeof(output), &pos,
|
||||||
"Whisper sent to %s\n", target_name);
|
"Whisper sent to %s\n", target_name);
|
||||||
|
|
@ -1649,6 +1656,12 @@ cleanup:
|
||||||
|
|
||||||
release_ip_connection(client->client_ip);
|
release_ip_connection(client->client_ip);
|
||||||
|
|
||||||
|
/* Remove channel callbacks before releasing refs to prevent use-after-free
|
||||||
|
* if a callback fires between the two releases. */
|
||||||
|
if (client->channel && client->channel_cb) {
|
||||||
|
ssh_remove_channel_callbacks(client->channel, client->channel_cb);
|
||||||
|
}
|
||||||
|
|
||||||
/* Release the callback reference (paired with addref before install_client_channel_callbacks) */
|
/* Release the callback reference (paired with addref before install_client_channel_callbacks) */
|
||||||
client_release(client);
|
client_release(client);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue