* Fix bad-free heap corruption in ppathstatus and psyncer (#391) Both ppathstatus.c and psyncer.c used bare free() via ptree_for_each_element_call_safe to bulk-free tree nodes that were allocated with pmem_malloc. pmem_malloc prepends a pmem_header_t to every allocation, so the returned pointer is an interior pointer to the underlying glibc chunk. Passing it to free() makes glibc read a garbage size field from the pmem header and abort with "free(): invalid size". This is the same class of bug fixed earlier in pintervaltree.c and pfscrypto.c. The crash manifests reliably with larger files because more sync-queue and path-status churn occurs, increasing the likelihood that one of these bulk-free paths is hit while a non-empty tree exists. Fix: add free_folder_tasks_node() (ppathstatus.c) and free_synced_down_folder() (psyncer.c) helpers that call pmem_free, and use them as the ptree_for_each_element_call_safe callback in all three affected call sites. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix bad-free in pfs.c and ppagecache.c (pcl-26j) Two more call sites passed bare free() as a callback to tree/list traversal macros, but the nodes were allocated via pmem_malloc which prepends a pmem_header_t. Freeing the data pointer directly skips the header and corrupts the heap. - pfs.c: ptree_for_each_element_call_safe on sectorsinlog used free() on psync_sector_inlog_t; replaced with free_sector_inlog_node() that calls pmem_free(PMEM_SUBSYS_OTHER, e). - ppagecache.c: psync_list_for_each_element_call on request->ranges used free() on psync_request_range_t; replaced with free_request_range() that calls pmem_free(PMEM_SUBSYS_CACHE, range). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add unit and smoke tests for pcl-26j bad-free (ppagecache, pfs, psyncer) Unit test (test_pcl26j_free): exercises all four fixed call sites — psync_request_range_t, synced_down_folder, folder_tasks_t, and psync_sector_inlog_t — using --wrap=malloc/free to verify that pmem_free() passes the header pointer to free(), not the data pointer. Includes a harness self-check that confirms bare free(data_ptr) is detected. Would have failed against pre-fix code. Smoke test (smoke-test-large-read.sh): builds pcloudcc with ASAN, starts the daemon, streams a large file (>=50 MB) from the FUSE mount to /dev/null to force multi-range psync_request_range_t allocation and teardown via psync_pagecache_free_request, then scans the ASAN log for any bad-free reports. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Levi Neely <lkn@darkstar.example.net> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .github/workflows | ||
| dev | ||
| doc | ||
| pclsync | ||
| tests | ||
| .clang-format | ||
| .clang-tidy | ||
| .envrc | ||
| .gitignore | ||
| CLI11.hpp | ||
| LOG-MANAGEMENT.md | ||
| Makefile | ||
| README.md | ||
| control_tools.cpp | ||
| control_tools.h | ||
| default.nix | ||
| detect_fuse.sh | ||
| flake.lock | ||
| flake.nix | ||
| main.cpp | ||
| pcloudcc.logrotate | ||
| pclsync_lib.cpp | ||
| pclsync_lib.h | ||
| rpcclient.cpp | ||
| rpcclient.h | ||
README.md
Introduction
pcloudcc is simple linux console client for pCloud cloud storage derived from the console-client developed by pCloud. This version is independently maintained by me, whose only affiliation with pCloud is as a user of their services. Due credit goes to Anton Titov, Ivan Stoev, and pCloud.
Supported Platforms & Distributions
The target operating system and platform for this program is linux/amd64, and has been reported to work on linux/aarch64. Program behavior on 32-bit architectures is considered undefined.
I aim to support as many distributions as possible. I maintain a package for AUR and Nix. I do not plan on providing or maintaining any other packages, but encourage anyone interested in doing so for their own distributions.
Compatibility Matrix
| Distribution | FUSE |
|---|---|
| Debian trixie | 2.x |
| Debian trixie | 3.x |
| Arch Linux (rolling) | 3.x latest |
| Fedora 41 | 3.x |
| Fedora (latest) | 3.x latest |
| Debian forky | 3.18+ |
| Slackware 15 | 3.10.5 |
All configurations require mbedTLS 3.x. Runtime mount testing was performed manually on FUSE 2 (libfuse 2.9.x), FUSE 3 (libfuse3 3.10.5), and FUSE 3.18+ (Debian forky container).
Notices
Security Notice
My code audits are best-effort, and I make security enhancements as I identify problems. However, I do not promise that this program is free of even older and well-known security vulnerabilities. Therefore, I recommend using this program only on a trusted single-user system. Security-related code audits and contributions are most welcome!
See Also
-
Contributing: Read this if you're interested in helping out. Short version: do your best to write good code, be courteous to maintainers, and most importantly: have fun!
-
Building: Read this if you're not sure how to build
pcloudcc. For most users,makeandmake installare enough. -
mbedtls 3.x migration notes: Read this if you use an older distribution such as
debian:bookwormand encounter build problems. -
Device Validation Guide: Read this if you're running
pcloudccand encounter device validation-related errors. -
Usage Guide: Read this if you're unsure how to start using
pcloudcc. -
Log Management Guide: Read this to configure log rotation, cache size limits, and custom log paths. To set up automatic log rotation, copy
pcloudcc.logrotateto/etc/logrotate.d/pcloudcc. -
pcloudcc-service: Container-based systemd service for running
pcloudccin userspace with podman. Includes multi-stage Dockerfile that buildspcloudccfrom source and Quadlet systemd unit for automated background syncing.