Fix pcl-aex.1: validate PCLOUD_LOG_PATH before use in psync_debug_path()

Add pdbg_path_is_safe() helper that rejects PCLOUD_LOG_PATH values
that are not absolute, contain '..' path components, or do not resolve
under the user HOME directory or /tmp. On rejection, fall back to the
default ~/.pcloud/debug.log path and emit a warning to stderr.

Also fix a pre-existing memory leak: ppath_home() return was not freed
in the default-path branch.

Ref GH #291.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-07 18:48:14 +01:00
parent 045aad673a
commit 7360bf4c52
1 changed files with 52 additions and 6 deletions

View File

@ -62,16 +62,60 @@ static void pdbg_init_level(void) {
__atomic_store_n(&pdbg_runtime_level, level, __ATOMIC_RELAXED);
}
/* Returns 1 if path is safe to use as a log file, 0 otherwise.
* Safe means: absolute, no '..' components, and under HOME or /tmp. */
static int pdbg_path_is_safe(const char *path) {
const char *home;
const char *p;
/* Must be an absolute path */
if (!path || path[0] != '/')
return 0;
/* Reject any '..' path component to prevent directory traversal */
p = path;
while (*p) {
while (*p == '/') p++;
if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0'))
return 0;
while (*p && *p != '/') p++;
}
/* Must resolve within the user home directory */
home = getenv("HOME");
if (home && home[0] == '/') {
size_t hlen = strlen(home);
if (strncmp(path, home, hlen) == 0 &&
(path[hlen] == '/' || path[hlen] == '\0'))
return 1;
}
/* Or within /tmp */
if (strncmp(path, "/tmp/", 5) == 0)
return 1;
return 0;
}
char *psync_debug_path() {
const char *custom_path = getenv("PCLOUD_LOG_PATH");
if (custom_path && custom_path[0] != '\0') {
size_t len = strlen(custom_path) + 1;
char *path = (char *)malloc(len);
if (!path) {
return NULL;
if (!pdbg_path_is_safe(custom_path)) {
/* Invalid path: reject and fall through to default */
fprintf(stderr,
"pdbg: PCLOUD_LOG_PATH '%s' rejected"
" (must be absolute, under HOME or /tmp, no '..' components);"
" using default log path\n",
custom_path);
} else {
size_t len = strlen(custom_path) + 1;
char *path = (char *)malloc(len);
if (!path) {
return NULL;
}
snprintf(path, len, "%s", custom_path);
return path;
}
snprintf(path, len, "%s", custom_path);
return path;
}
char *home = ppath_home();
@ -83,10 +127,12 @@ char *psync_debug_path() {
size_t len = strlen(home) + strlen(subdir) + 1;
char *sockpath = (char *)malloc(len);
if (!sockpath) {
free(home);
return NULL;
}
snprintf(sockpath, len, "%s%s", home, subdir);
free(home);
return sockpath;
}