Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/daemon/ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1336,12 +1336,18 @@ static bool private_log_base_name_valid(const char *base_name) {
}

static char *private_log_directory_path_copy(const char *directory_path) {
#ifdef __APPLE__
/* Darwin exposes the trusted top-level aliases /tmp -> /private/tmp and
* /var -> /private/var. Resolve only those root-owned aliases before the
#if defined(__APPLE__) || defined(__FreeBSD__)
/* Resolve only those root-owned aliases before the
* component-wise O_NOFOLLOW walk. Canonicalizing the complete caller path
* would follow an attacker-controlled cache/log symlink and is forbidden. */
#if defined(__APPLE__)
/* Darwin exposes the trusted top-level aliases /tmp -> /private/tmp and
* /var -> /private/var. */
static const char *const aliases[] = {"/tmp", "/var"};
#else
/* FreeBSD additionally exposes /home -> /usr/home as a root-owned alias. */
static const char *const aliases[] = {"/tmp", "/var", "/home"};
#endif
for (size_t index = 0; index < sizeof(aliases) / sizeof(aliases[0]); index++) {
const char *alias = aliases[index];
size_t alias_length = strlen(alias);
Expand Down
55 changes: 43 additions & 12 deletions src/daemon/runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ void cbm_daemon_runtime_force_peer_image_unverified_for_testing(bool force) {
#include <sys/proc_info.h>
#include <sys/stat.h>
#include <unistd.h>
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#if defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#endif

enum {
Expand Down Expand Up @@ -146,7 +150,7 @@ typedef struct {
HANDLE file;
BY_HANDLE_FILE_INFORMATION information;
LARGE_INTEGER size;
#elif defined(__APPLE__) || defined(__linux__)
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
int fd;
struct stat status;
#endif
Expand Down Expand Up @@ -501,7 +505,7 @@ static bool runtime_activation_response_decode(
static uint64_t runtime_current_process_id(void) {
#ifdef _WIN32
return (uint64_t)GetCurrentProcessId();
#elif defined(__APPLE__) || defined(__linux__)
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
return (uint64_t)getpid();
#else
return 0;
Expand All @@ -515,7 +519,7 @@ static void runtime_process_image_reference_init(runtime_process_image_reference
memset(reference, 0, sizeof(*reference));
#ifdef _WIN32
reference->file = INVALID_HANDLE_VALUE;
#elif defined(__APPLE__) || defined(__linux__)
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
reference->fd = -1;
#endif
}
Expand All @@ -529,7 +533,7 @@ static bool runtime_process_image_reference_release(runtime_process_image_refere
if (reference->file != INVALID_HANDLE_VALUE && !CloseHandle(reference->file)) {
ok = false;
}
#elif defined(__APPLE__) || defined(__linux__)
#elif defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
if (reference->fd >= 0 && close(reference->fd) != 0) {
ok = false;
}
Expand Down Expand Up @@ -669,9 +673,9 @@ static bool runtime_mac_process_maps_file_executable(int process_id, const struc
return false;
}

#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)

static bool runtime_linux_stat_same_image(const struct stat *first, const struct stat *second) {
static bool runtime_posix_stat_same_image(const struct stat *first, const struct stat *second) {
return first && second && S_ISREG(first->st_mode) && S_ISREG(second->st_mode) &&
first->st_dev == second->st_dev && first->st_ino == second->st_ino &&
first->st_size == second->st_size && first->st_mtim.tv_sec == second->st_mtim.tv_sec &&
Expand Down Expand Up @@ -780,11 +784,11 @@ static bool runtime_process_image_reference_acquire(
(!fingerprint ||
cbm_daemon_build_fingerprint_native_file((uintptr_t)image_fd, fingerprint)) &&
fstat(image_fd, &image_after) == 0 &&
runtime_linux_stat_same_image(&image_before, &image_after);
runtime_posix_stat_same_image(&image_before, &image_after);
int verify_fd = ok ? openat(process_fd, "exe", O_RDONLY | O_CLOEXEC) : -1;
struct stat verify_status;
ok = ok && verify_fd >= 0 && fstat(verify_fd, &verify_status) == 0 &&
runtime_linux_stat_same_image(&image_after, &verify_status);
runtime_posix_stat_same_image(&image_after, &verify_status);
if (verify_fd >= 0 && close(verify_fd) != 0) {
ok = false;
}
Expand All @@ -798,6 +802,33 @@ static bool runtime_process_image_reference_acquire(
} else if (image_fd >= 0) {
(void)close(image_fd);
}
#elif defined(__FreeBSD__)
if (process_id > INT_MAX) {
return false;
}
int pid = (int)process_id;
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid};
char path[PATH_MAX];
size_t path_length = sizeof(path);
bool ok = sysctl(mib, 4, path, &path_length, NULL, 0) == 0 && path_length > 0;
if (ok) {
path[path_length < sizeof(path) ? path_length : sizeof(path) - 1] = '\0';
}
int image_fd = ok ? open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK) : -1;
struct stat image_before;
struct stat image_after;
ok = image_fd >= 0 && fstat(image_fd, &image_before) == 0 && S_ISREG(image_before.st_mode) &&
(!fingerprint ||
cbm_daemon_build_fingerprint_native_file((uintptr_t)image_fd, fingerprint)) &&
fstat(image_fd, &image_after) == 0 &&
runtime_posix_stat_same_image(&image_before, &image_after);
if (ok) {
reference->held = true;
reference->fd = image_fd;
reference->status = image_after;
} else if (image_fd >= 0) {
(void)close(image_fd);
}
#else
(void)process_id;
bool ok = false;
Expand Down Expand Up @@ -838,14 +869,14 @@ static bool runtime_process_image_reference_matches_process(
runtime_mac_stat_same(&active->status, &peer.status);
bool released = runtime_process_image_reference_release(&peer);
return same && released;
#elif defined(__linux__)
#elif defined(__linux__) || defined(__FreeBSD__)
runtime_process_image_reference_t peer;
runtime_process_image_reference_init(&peer);
bool same = runtime_process_image_reference_acquire(process_id, &peer, NULL);
struct stat active_now;
same = same && fstat(active->fd, &active_now) == 0 &&
runtime_linux_stat_same_image(&active->status, &active_now) &&
runtime_linux_stat_same_image(&active->status, &peer.status);
runtime_posix_stat_same_image(&active->status, &active_now) &&
runtime_posix_stat_same_image(&active->status, &peer.status);
bool released = runtime_process_image_reference_release(&peer);
return same && released;
#else
Expand Down
1 change: 1 addition & 0 deletions tests/test_stack_overflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

/* tree-sitter runtime allocator hooks (ts_runtime/src/alloc.h, TS_PUBLIC) and
* mimalloc (vendored) — for the #424 allocator-binding regression test. */
Expand Down
Loading