Compare commits

..

1 Commits

Author SHA1 Message Date
TapTap 80768d64d4 fix: security issues #192 #191 #190 #189 #188 #187 2026-07-30 18:49:25 +02:00
5 changed files with 86 additions and 16 deletions
+52
View File
@@ -345,11 +345,63 @@ ParallelScanner* parallel_scanner_create(char* root_directory, bool use_metadata
char* cur_path = path_cat(root_directory, entry->d_name);
if (!cur_path)
continue;
struct stat lstats;
if (lstat(cur_path, &lstats) != 0) {
free(cur_path);
continue;
}
bool is_symlink = S_ISLNK(lstats.st_mode);
// Skip symlinks unless the user explicitly enabled following/copying them.
if (is_symlink && !follow_symlinks && !copy_links && !safe_links &&
!copy_unsafe_links) {
free(cur_path);
continue;
}
// --safe-links: reject symlinks pointing outside the source tree.
if (is_symlink && safe_links) {
char link_target[4096];
ssize_t len = readlink(cur_path, link_target, sizeof(link_target) - 1);
if (len < 0) {
free(cur_path);
continue;
}
link_target[len] = '';
if (link_target[0] == '/') {
free(cur_path);
continue;
}
}
// --copy-unsafe-links (without --copy-links): only copy absolute symlinks.
if (is_symlink && copy_unsafe_links && !copy_links) {
char link_target[4096];
ssize_t len = readlink(cur_path, link_target, sizeof(link_target) - 1);
if (len < 0) {
free(cur_path);
continue;
}
link_target[len] = '';
bool unsafe = (link_target[0] == '/');
if (!unsafe) {
free(cur_path);
continue;
}
}
// Determine whether to use lstat or stat results for the entry.
struct stat st;
bool use_lstat_res = is_symlink && follow_symlinks && !copy_links;
if (use_lstat_res) {
st = lstats;
} else {
if (stat(cur_path, &st) != 0) {
free(cur_path);
continue;
}
}
if (S_ISDIR(st.st_mode)) {
array_list_add(subdirs, cur_path);
} else {
+20
View File
@@ -12,6 +12,9 @@
#include "metadata.h"
#include "protocol.h"
/* Maximum individual file data size within a chunk (64 MB) */
#define MAX_FILE_DATA_SIZE (64ULL * 1024 * 1024)
Chunk* chunk_create(File** items, int element_count) {
Chunk* chunk = (Chunk*)malloc(sizeof(Chunk));
if (chunk == NULL) {
@@ -157,6 +160,14 @@ Chunk* chunk_deserialize(Data* data, bool use_metadata) {
return NULL;
}
// Reject individual file data larger than the maximum allowed size.
if (file_data_size > MAX_FILE_DATA_SIZE) {
log_message(LOG_LEVEL_ERROR, "File data size %zu exceeds maximum %llu",
file_data_size, (unsigned long long)MAX_FILE_DATA_SIZE);
array_list_delete(files);
return NULL;
}
void* file_data = malloc(file_data_size);
if (file_data == NULL) {
perror("Could not allocate memory for file data");
@@ -210,6 +221,15 @@ Chunk* receive_chunk_data(int fd, const Config* config) {
return NULL;
}
}
// Reject chunks larger than the maximum allowed size to prevent OOM.
if (data_to_process->size > MAX_CHUNK_SIZE) {
log_message(LOG_LEVEL_ERROR, "Chunk size %zu exceeds maximum %llu",
data_to_process->size, (unsigned long long)MAX_CHUNK_SIZE);
data_destroy(data_to_process);
return NULL;
}
Chunk* chunk = chunk_deserialize(data_to_process, config->use_metadata);
data_destroy(data_to_process);
if (chunk == NULL)
+1 -2
View File
@@ -35,8 +35,7 @@ File* file_create(const char* path) {
return NULL;
}
memcpy(file->path, path, path_len);
file->path[path_len] = '\0';
strcpy(file->path, path);
file->data = data_create_reserve(0);
if (file->data == NULL) {
free(file->path);
+3
View File
@@ -11,6 +11,9 @@
/* Maximum allowed data payload size for receive_data (100 MB) */
#define MAX_DATA_PAYLOAD_SIZE (100ULL * 1024 * 1024)
/* Maximum chunk size (64 MB) — prevents unbounded allocation from the wire */
#define MAX_CHUNK_SIZE (64ULL * 1024 * 1024)
typedef struct ssl_st SSL;
typedef int Status;
+8 -12
View File
@@ -13,7 +13,7 @@ bool mkdir_r(const char* path) {
char* path_duplicate = malloc(strlen(path) + 1);
if (!path_duplicate)
return false;
memcpy(path_duplicate, path, strlen(path) + 1);
strcpy(path_duplicate, path);
char* path_current = (char*)malloc((strlen(path) + 2) * sizeof(char));
if (!path_current) {
free(path_duplicate);
@@ -21,8 +21,7 @@ bool mkdir_r(const char* path) {
}
char* path_current_position = path_current;
if (path[0] == '/') {
path_current[0] = '/';
path_current[1] = '\0';
strcpy(path_current, "/");
path_current_position += 1;
} else {
path_current[0] = '\0';
@@ -32,12 +31,10 @@ bool mkdir_r(const char* path) {
const char* part = strtok_r(path_duplicate, delimiter, &saveptr);
bool ok = true;
while (part != NULL) {
size_t part_len = strlen(part);
memcpy(path_current_position, part, part_len);
path_current_position += part_len;
path_current_position[0] = '/';
path_current_position[1] = '\0';
path_current_position++;
strcpy(path_current_position, part);
path_current_position += strlen(part) * sizeof(char);
strcpy(path_current_position, "/");
path_current_position += sizeof(char);
struct stat st;
if (stat(path_current, &st) != 0) {
if (mkdir(path_current, 0755) != 0) {
@@ -56,9 +53,8 @@ bool mkdir_r(const char* path) {
char* str_dup(const char* string) {
if (string == NULL)
return NULL;
size_t str_len = strlen(string);
char* new_string = (char*)malloc(str_len + 1);
memcpy(new_string, string, str_len + 1);
char* new_string = (char*)malloc(strlen(string) + 1);
strcpy(new_string, string);
return new_string;
}