Commit Graph

251 Commits

Author SHA1 Message Date
Levi Neely d50749755a Fix init handler signature for FUSE 3
FUSE 3 init handler requires struct fuse_config* parameter.
This parameter provides access to high-level API configuration
options that can be modified during initialization.

Without this parameter, the init handler signature is incompatible
with FUSE 3, causing filesystem operations to fail.
2026-03-09 20:52:10 +01:00
Levi Neely c2669e3d2b Remove deprecated FUSE options nonempty and hard_remove
- nonempty: Removed in FUSE 3.0, mounting on non-empty directories is now default behavior
- hard_remove: High-level API option not available in FUSE 3, immediate unlink is standard

These options are no longer recognized by FUSE 3 and cause mount errors.
2026-03-09 20:52:10 +01:00
Levi Neely 72d8102db1 Migrate to FUSE 3.x API
- Update FUSE_USE_VERSION from 26 to 30
- Replace fuse_mount/fuse_unmount with fuse_session_mount/fuse_session_unmount
- Update fuse_new() to take args first, remove channel parameter
- Add flags parameter to readdir handler (enum fuse_readdir_flags)
- Add flags parameter to rename handler (for renameat2 support)
- Update filler function calls to include FUSE_FILL_DIR_PLUS flag
- Merge ftruncate into truncate handler (FUSE 3 combines them)
- Update fuse_loop_mt to fuse_loop_mt_31 with loop config
- Link against libfuse3 instead of libfuse
- Remove fuse_chan usage (deprecated in FUSE 3)

Addresses #342
2026-03-09 20:52:10 +01:00
Levi Neely 90945b8817
Fix debug build: compile error, false-positive abort, crash DB lock (#372)
* Fix debug build: compile error, false-positive abort, and crash DB lock

- psql_debug.c: add forward declaration for psql_do_prepare to fix
  conflicting-types compile error (BUILD=debug was broken entirely)

- pfs_debug.c: change pfs_debug_check_lock_order from abort to log-only;
  write paths legitimately take file lock before SQL and handle ordering
  via psql_trylock()+relock in pfs_reopen_file_for_writing — no actual
  deadlock risk, the check was a false positive

- psignal.c/h: add psignal_register_cleanup() hook mechanism; change
  panic() to use _exit(1) instead of abort() so all file descriptors are
  closed on crash, releasing SQLite WAL POSIX advisory locks immediately
  and preventing ASan from hanging the process as a zombie

- psql.c: register psql_panic_cleanup() hook to close the DB on panic
  (belt-and-suspenders alongside _exit fd cleanup)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix debug psql_trylock: missing strong override left lockctr unupdated

The weak psql_trylock() stub in psql.c called plocks_trywrlock() directly
without updating lockctr. In the debug build, psql_unlock() asserts
lockctr > 0, so when trylock succeeded (lock acquired, lockctr still 0)
the assert fired with SIGABRT on write ops via pfs_inc_writeid_locked.

Add a strong psql_trylock() override in psql_debug.c that delegates to
psql_do_trylock(), which properly acquires the rwlock and updates lockctr.

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>
2026-03-09 20:49:09 +01:00
Levi Neely 358ae595e9
Add memory accounting per subsystem (#371)
* Implement memory accounting infrastructure

* Migrate malloc/calloc to pmem_malloc with subsystem tracking

* Add overflow-safe pmem_malloc_array function

* Migrate pfstasks.c malloc/free to pmem_malloc/pmem_free

* Migrate pnetlibs.c malloc/free to pmem_malloc/pmem_free

* Fix multiplication patterns in pnetlibs.c with pmem_malloc_array

* Migrate ppagecache.c malloc/free to pmem_malloc/pmem_free

* Fix remaining multiplication pattern in ppagecache.c line 3239

* Migrate pssl.c malloc/free to pmem_malloc/pmem_free

* Migrate pcryptofolder.c malloc/free to pmem_malloc/pmem_free

* Migrate pfolder.c malloc/free to pmem_malloc/pmem_free

* Fix multiplication patterns in pfolder.c with overflow checks

* Migrate publiclinks.c malloc/free to pmem_malloc/pmem_free

* Migrate plocalscan.c malloc/free to pmem_malloc/pmem_free

* Migrate psql.c malloc/free to pmem_malloc/pmem_free

* Migrate putil.c malloc/free to pmem_malloc/pmem_free

* Fix multiplication patterns in putil.c encoding functions with overflow checks

* Migrate pfsupload.c malloc/free to pmem_malloc/pmem_free

* Migrate pdiff.c malloc/free to pmem_malloc/pmem_free

* Migrate pcrypto.c malloc/free to pmem_malloc/pmem_free

* Migrate pupload.c malloc/free to pmem_malloc/pmem_free

* Migrate psock.c malloc/free to pmem_malloc/pmem_free

* Fix multiplication pattern in psock.c with overflow checks

* Add panic() with backtrace to psignal module

* Register panic handlers early in main()

* Fix panic() infinite recursion by unregistering handlers before abort()

* Migrate remaining 34 files to pmem_malloc/pmem_free

* Migrate papi.c, ptools.c, pbusinessaccount.c to PMEM_SUBSYS_API

* Fix pcache.c compilation errors - replace he->pmem_free with pmem_free

* Add pmem.h include to pdbg.c

* Add pmem.h include to 10 files missing it

* Fix ptask.c compilation errors - replace s->pmem_free with s->free

* Fix ptask.c callback arguments - remove PMEM_SUBSYS_OTHER from s->free calls

* Fix pmem.c infinite recursion - use raw malloc/free internally

* Fix prand.c mixed allocation - use pmem_free for putil_strdup result

* Migrate psettings.c free() calls to pmem_free()

* Fix all remaining stray free() calls - migrate to pmem_free()

* Fix pnetlibs_debug.c free() call - migrate to pmem_free()

* Add missing pmem.h include to pdevice.c

* Migrate pclsync_lib.cpp free() calls to pmem_free()

* Fix pfolder.c psync_free_string_list to use pmem_free()

* Fix all psync_list_for_each_element_call to use pmem_free wrappers

* Fix all list free wrapper functions - add proper definitions

* Fix rpcclient.cpp mixed allocation - use pmem_free for prpc_sockpath

* Replace all realloc() calls with pmem_realloc()

* Replace all strdup() calls with putil_strdup()

* Fix rpcclient.cpp allocation boundary - use plain malloc/free for RPC responses

* Fix RPC response length calculation - include header size

* Fix control_tools.cpp mixed allocations - use pmem_free for pshm_read results

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 21:47:22 +01:00
Levi Neely 8276034f70
Add lock ordering assertions in debug builds (#370)
* Add lock ordering assertions for psql_lock → file mutex

* Add missing psql.h include to pfs.h

* Fix debug build conditional compilation for lock ordering assertions

* Fix function declaration order for pfs_debug_check_lock_order

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 15:38:41 +01:00
Levi Neely d0c213f181
Add overflow-safe allocation wrapper pmem_calloc_safe() (#369)
* Add overflow-safe allocation wrappers to pmem module

* Replace malloc(nmemb*size) with pmem_calloc_safe in high-risk sites

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 14:55:21 +01:00
Levi Neely 89ef8663b0
Add psignal module for centralized signal handling (#368)
* Add psignal module for centralized signal handling

- Added pclsync/psignal.h with psignal_register() and psignal_check_pending() API
- Added pclsync/psignal.c with async-signal-safe handlers for SIGINT, SIGTERM, SIGHUP
- Implements flag-based deferred signal handling pattern

* Integrate psignal into main loop and remove conflicting handlers

- Added extern "C" linkage to psignal.h for C++ compatibility
- Integrated psignal_check_pending() into pclsync_lib.cpp main loop
- Integrated psignal_check_pending() into ptimer.c timer loop
- Removed conflicting signal handlers from pfs.c

* Migrate psync_set_signal to psignal module

- Added psignal_set_custom_handler() to psignal.h and psignal.c
- Replaced psync_set_signal() calls in pfs.c with psignal_set_custom_handler()
- Centralizes all signal handling in psignal module

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 14:27:21 +01:00
Levi Neely 9d4143f1f0
Add clang-tidy signal safety checks (pcl-2s2.2) (#367)
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 13:41:51 +01:00
Levi Neely 5ad532b692
Add NULL check audit to high-risk allocations (#366)
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 13:11:41 +01:00
Levi Neely f9e362fd24
Add signal safety test suite (#365)
* Add signal safety test suite

* Remove binary file from repository

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 12:07:30 +01:00
Levi Neely 645596ac15
Add deadlock detection with timeouts (#364)
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-08 11:55:25 +01:00
Levi Neely 5769bb4882
Fix pcl-10w: remove IS_DEBUG conditional from psql.h (#363)
Removed IS_DEBUG conditional block from psql.h. Added psql_dump_locks() declaration. Now uses single API without debug/release variants. This eliminates the last remaining use of IS_DEBUG after PR #177.

Fixes #178

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-07 21:37:21 +01:00
Levi Neely 6a0edf0cc3
Fix pcl-ivv: remove weak attribute from debug hooks (#362)
Removed weak attribute from debug hooks (psys_debug_abort_on_sqllock and psys_debug_configure_core_dump). Made functions static in psys.c and removed declarations from psys.h. Functions can no longer be overridden by external libraries, preventing potential code execution and security bypass.

Fixes #289

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-07 20:18:51 +01:00
Levi Neely 431f94725f
Fix pcl-r0j: rename psync_delete_sync_by_folderid to pfolder_delete_sync_by_id (#361)
Renamed psync_delete_sync_by_folderid to pfolder_delete_sync_by_id to align with pfolder API naming conventions. Updated all callers.

Fixes #100

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-07 19:54:21 +01:00
Levi Neely 1bf831c00f
Fix pcl-ue8: operator precedence in GetState() (#360)
Separated assignment from condition so rep contains Call() return value.
Removed incorrect wrapper that prevented state checks from executing.
Now rep values 10/11/12 properly set state.

Fixes #180

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-07 19:40:07 +01:00
Levi Neely f17fb19b85
Fix log file permissions: use mode 0600 (#359)
Replace fopen() with open()+fdopen() for all log file creation
in pdbg.c to ensure files are created with mode 0600, preventing
world-readable logs that may contain sensitive information.

Fixes #290

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-07 19:20:51 +01:00
Levi Neely e37c7f5894
Fix pcl-dls: errPtr memory leak between ptools_backend_call() calls in ptools_set_backend_file_dates() (#358)
* Fix pcl-dls.1: free errPtr between calls in ptools_set_backend_file_dates()

char *errPtr was already used instead of char msgErr[1024], but was
not freed between the two ptools_backend_call() invocations. If the
first call allocated errPtr, the second would overwrite the pointer
without freeing it. Add free(errPtr); errPtr = NULL; between the two
calls to eliminate the leak.

Ref GH #194.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add ptools_set_backend_file_dates() errPtr lifecycle tests (pcl-dls)

6 test cases using malloc/free wrapping covering both-succeed,
call1-error, call2-error, both-errors, pre-fix leak demonstration,
and no-double-free after mid-free NULLing.

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>
2026-03-07 19:01:17 +01:00
Levi Neely 0430d0b872
Fix pcl-aex: validate PCLOUD_LOG_PATH to prevent arbitrary file write and log injection (#357)
* 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>

* Add PCLOUD_LOG_PATH path-safety tests (pcl-aex)

28 test cases covering relative paths, '..' traversal, paths outside
HOME and /tmp, valid accepted paths, and psync_debug_path() env
fallback behaviour.

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>
2026-03-07 18:53:17 +01:00
Levi Neely 045aad673a
Fix pcl-aqb: pthread_create unchecked return, thread_data leak, and function-pointer cast UB in prun.c (#356)
* Fix pcl-aqb.1: eliminate function-pointer cast UB in start_thread() via union

Replace the single void* run field in thread_data with a union
{ thread0_run run0; thread1_run run1 } so each function pointer is
stored and retrieved at its correct type, eliminating the
thread0_run <-> thread1_run cast chain UB. Split start_thread() into
prun_thread() and prun_thread1() that each populate the appropriate
union member, backed by a shared start_thread_common() helper. Add
malloc NULL check with error log in both public functions.
pthread_create failure handling (log + free) was already present.

Ref GH #199.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add prun start_thread() resource-leak and UB tests (pcl-aqb)

8 test cases using linker interposition covering pthread_create
failure data-free, attr_destroy on failure, malloc failure graceful
return, union fn storage without cast, and success path accounting.

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>
2026-03-07 18:44:47 +01:00
Levi Neely 60e43edec4
Fix pcl-a1j: buffer overflow in ptools_create_backend_event() via unchecked sprintf and strcat (#355)
* Fix pcl-a1j.1: replace sprintf with snprintf and add strcat length check in ptools_create_backend_event()

Add paramname length check (> 254 bytes → skip with warning) before
snprintf into charBuff[i][258], and validate the snprintf return
value. Add explicit length check before strcat into keyParams to
prevent overflow when paramname exceeds remaining buffer space.
Eliminates buffer overflow from long paramname.

Ref GH #195.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Fix pcl-a1j.1: clamp pCnt to PTOOLS_MAX_PARAMS to prevent charBuff stack overflow

charBuff[30][258] is a fixed-size stack array but pCnt was unbounded,
allowing any caller with params->paramCnt > 30 to overflow the stack
via charBuff[i] access. Add PTOOLS_MAX_PARAMS (30) define, use it to
size charBuff, and clamp pCnt to PTOOLS_MAX_PARAMS with a warning log
before the loop.

Ref GH #195.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add ptools_create_backend_event() validation tests (pcl-a1j)

11 test cases covering pCnt clamping, paramname length guards,
snprintf boundary, keyParams overflow check, and comma-prefix
for subsequent params.

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>
2026-03-07 18:35:43 +01:00
Levi Neely d5a1c74c43
Fix pcl-6nb: readResponse buffer over-read via unchecked msg->length (#354)
* Fix pcl-6nb.1: readResponse buffer over-read in rpcclient.cpp

Replace malloc'd receive buffer with stack array, fix the broken
validation (msg->length compared against POVERLAY_BUFSIZE rather
than max_value_size which excluded the header), fix the payload-read
loop target (msg->length already includes the header, so the old
`header_size + msg->length` limit over-read), add the missing
`msg->length > total_read` guard before memcpy, and add EINTR
handling in the read loop. Eliminates heap over-read when the daemon
sends msg->length > POVERLAY_BUFSIZE.

Ref GH #184.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* Add readResponse validation tests (pcl-6nb)

Six socketpair-based test cases covering oversized msg->length,
total_read underrun, header underflow, truncated header, valid
message, and exact-boundary acceptance.

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>
2026-03-07 18:08:56 +01:00
Levi Neely 5a519ab675
Fix pcl-3la: pstatus saturating add and fuse thread cleanup (#352)
* Fix pcl-3la.1: saturating addition for bytestou in pstatus_upload_recalc

Replace unchecked uint64_t summation in pstatus_upload_recalc() with
overflow-safe saturating addition. Before adding each file's size,
check if the result would wrap around UINT64_MAX; if so, saturate to
UINT64_MAX instead of silently wrapping.

Ref GH #293.

* Fix pcl-3la.2: remove spurious fuse_loop_mt while-loop and exit(0)

fuse_loop_mt() already loops internally; wrapping it in an additional
while loop caused repeated re-entry after normal exit. Also removes
the exit(0) call in the shutdown path so fuse_destroy() and other
cleanup run properly on shutdown.

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>
2026-03-07 16:24:53 +01:00
Levi Neely 7a8aef3b50
Fix pcl-5xn.1: replace pthread_cond_wait with timedwait in pstatus_wait (#353)
Replace indefinite pthread_cond_wait() calls in pstatus_wait() with
pthread_cond_timedwait() using a 5-second timeout computed via
clock_gettime(CLOCK_REALTIME). On timeout, the while loop re-evaluates
the wait condition, preventing indefinite hang when the state machine
stalls.

Ref GH #292.

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-07 16:23:48 +01:00
Levi Neely 18e9c8231c
Fix signal handler safety issues (pcl-2tv) (#351)
- Use sig_atomic_t flag instead of calling unsafe functions in signal handlers
- Remove pdbg_logf() and exit() calls from psync_signal_handler
- Check shutdown_requested flag in main loops
- Export flag for cross-module access

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-06 21:34:00 +01:00
Levi Neely 48b34a47a6
Fix pcl-zqv.4.3: socket lifecycle and fd management in psock.c (#349)
- connect_res(): add SO_ERROR check after EINPROGRESS + wait_writable;
  a refused/reset connection makes the socket writable with SO_ERROR
  set — previously returned the socket as 'connected' when it was not.
  Added psock_check_so_error() helper using getsockopt(SO_ERROR).

- wait_readable(), wait_writable(), wait_ssl_ready(): wrap select() in
  do{...}while(errno==EINTR) with fd_set reinit on each iteration.
  Signal delivery during blocking waits previously caused immediate
  SOCKET_ERROR return, dropping live connections on any signal.
  Linux updates tv on EINTR to reflect remaining time; reinitializing
  fd_set before each retry ensures a clean select state.

- psync_socket_read_plain(), psync_socket_readall_plain(),
  psync_socket_readall_plain_thread(): add EINTR to EAGAIN/EWOULDBLOCK
  retry condition on read(). EINTR is a non-fatal interruption; retrying
  is correct and consistent with the non-blocking socket model.

- psync_socket_read_noblock_plain(): return PSYNC_SOCKET_WOULDBLOCK on
  EINTR rather than -1 (fatal error); callers handle WOULDBLOCK by
  scheduling a retry.

- psync_socket_writeall_plain(), psync_socket_writeall_plain_thread():
  add EINTR retry path on write() without a write-timeout wait, since
  EINTR does not indicate the socket became unwritable.

- psock_connect(): add null check on malloc(sizeof(psock_t)); on OOM,
  close the connected fd and free the SSL context before returning NULL.

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 19:13:18 +01:00
Levi Neely 874e25f11b
Fix pcl-zqv.4.2: protocol parsing and buffer safety in prpc/papi (#348)
prpc.c:
- on_request: fix total_size computation. The original formula
  sizeof(uint32_t)+sizeof(uint64_t)+response->length had two bugs:
  (1) sizeof(uint32_t)+sizeof(uint64_t)=12 but offsetof(rpc_message_t,value)=16
  due to struct alignment padding between the uint32_t type and uint64_t length
  fields; and (2) respond() was storing full message size in response->length,
  double-counting the header. Fix: use offsetof(rpc_message_t,value)+response->length,
  consistent with readResponse() in rpcclient.cpp which reads a fixed header_size
  of offsetof(rpc_message_t,value) bytes then reads msg->length payload bytes.
- respond: store payload length only in response->length (value_length+1),
  not full message size, to match the client protocol expectation.
- prpc_init: add null check on malloc return value.
- prpc_register: restore old handler table and return -1 if prpc_init fails.

papi.c:
- papi_result_thread: add missing MAX_API_RESPONSE_SIZE guard (present in
  papi_result but absent here), preventing server-controlled unbounded malloc.
- papi_result, papi_result_thread: add null checks on malloc before passing
  pointer to psock_readall.
- papi_result_async: add MAX_API_RESPONSE_SIZE check and malloc null check
  on reader->respsize path.
- calc_ret_len: add _NEED_DATA(1) guard before ARRAY and HASH while-loop
  conditions; empty containers with datalen=0 caused out-of-bounds read.

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 19:02:01 +01:00
Levi Neely 07e4189bae
Fix pcl-g46: make psync_status queue fields atomic in status_change_thread (#347)
status_change_thread reads psync_status.filestodownload, filestoupload,
localisfull, and remoteisfull under statusmutex, while pstatus_download_recalc,
pstatus_upload_recalc, and pstatus_set write them without statusmutex (or under
a different mutex). TSan reports the race at pqevent.c:274.

Replace all writes of these four fields with __atomic_store_n and capture
atomic snapshots in status_change_thread before the condition, using the
snapshots for both comparison and the status_old update after struct copy.
Also use atomic loads in calc_status() for filestodownload and filestoupload.

Closes #335

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 18:36:12 +01:00
Levi Neely 3cc42792b5
Fix pcl-bga: make psync_status.status accesses atomic (#346)
psync_status.status is written in pstatus_set() (pstatus.c:263) after
releasing status_internal_mutex, while status_change() (pclsync_lib.cpp:435)
reads it concurrently from the callback thread without any lock. TSan
reports the race between T9 (write in pstatus_set) and the status callback
thread (read in status_change).

Replace all reads and writes of psync_status.status with
__atomic_load_n/__atomic_store_n (__ATOMIC_RELAXED) across pstatus.c,
pqevent.c, and pclsync_lib.cpp. In status_change_thread, capture the
atomic value once into cur_status before the condition to avoid multiple
inconsistent loads. In status_change(), capture cur_status at entry and
use it throughout, also propagating it to the copied status_ struct.

Closes #334

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 18:24:35 +01:00
Levi Neely 5aae38cbd8
Fix pcl-96f: make psync_current_time accesses atomic (#345)
psync_current_time is a global time_t written by timer_thread without
holding timer_mutex, while ptimer_register reads it under timer_mutex.
TSan reports the race at ptimer.c:152 (write) and ptimer.c:216 (read).

Replace all reads with __atomic_load_n and all writes with
__atomic_store_n using __ATOMIC_RELAXED. This covers the race sites in
ptimer.c and all external readers in plocalscan.c, pnetlibs.c, and
psynclib.c that access psync_current_time without any mutex.

Closes #333

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 18:14:33 +01:00
Levi Neely 9c721bde00
Fix data race on task refcount in psync_task_free (#344)
Acquire mutex before reading tm->refcnt to prevent race with
psync_task_dec_refcnt(). Fixes ThreadSanitizer warning.

Fixes #332

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-03 21:15:57 +01:00
Levi Neely ede53b6b89
Fix pcl-0c1: make pdbg_runtime_level atomic (#343)
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-03 20:08:18 +01:00
Levi Neely 5ce7118a35
Fix pcl-zqv.4.12: add bounds check in trim_der_key (#341)
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-03 19:53:01 +01:00
Levi Neely 51dd304543
Delete test_deadlock_forced (#340) 2026-03-03 19:35:24 +01:00
Levi Neely 40fd38dde5
Fix pcl-zqv.5.7: eliminate deadlock in pfs_get_both_locks (#339)
* Fix pcl-zqv.5.7: eliminate deadlock in pfs_get_both_locks

- Enforce consistent lock ordering: always acquire psql lock before file mutex
- Remove retry loop that could spin indefinitely
- Replace abort() with error return in pfs_lock_file timeout
- Add unit test verifying lock ordering prevents deadlock

Fixes GH #258

* Reorganize tests: smoke-tests, fault-inject, unit-tests

* Reorganize tests: smoke-tests, fault-inject, unit-tests

* Remove validation report

---------

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-03 19:33:56 +01:00
Levi Neely 63d8685240
Fix psync_my_pass wipe to use strlen instead of sizeof pointer (#338)
In psync_unlink(), putil_wipe(psync_my_pass, sizeof(psync_my_pass))
only wiped 8 bytes (pointer size) instead of the full password string.
Changed to strlen(psync_my_pass) and added NULL check.

Fixes pcl-zqv.9.1 (partial)
GH #276

Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-03 17:11:10 +01:00
Levi Neely 7175636e49
Add .kiro and .claude to .gitignore (#337)
Co-authored-by: Levi Neely <lkn@darkstar.example.net>
2026-03-03 17:01:27 +01:00
Levi Neely d31b009acd
Fix data race on lastseed in prand_seed() (#330)
Mutex protects lastseed read/write
2026-03-03 16:43:59 +01:00
Levi Neely 72ef56652d
Fix race condition in pfs_reopen_file_for_writing encoder state (#329)
Crypto folder operations tested, no regression
2026-03-03 16:18:16 +01:00
Levi Neely 3e777665b6
Fix race condition in pfs_dec_of_refcnt (#328)
File operations tested, no regression
2026-03-03 16:13:22 +01:00
Levi Neely cb938aa128
Fix memory leak in pfs_update_openfile on collision (#327)
File operations tested, no regression
2026-03-03 16:10:18 +01:00
Levi Neely 07cbef9b88
Add write-permission check in pfs_write and pfs_ftruncate (#326)
Write and truncate operations tested, work correctly
2026-03-03 16:05:28 +01:00
Levi Neely c03a37527f
Fix NULL-deref in pfs_rename_openfile_locked (#325)
File rename tested, works correctly
2026-03-03 15:58:07 +01:00
Levi Neely 6ce166a0a5
Fix integer overflow in fake fileid calculation (#324)
Filesystem tested, file creation and removal work
2026-03-03 15:54:50 +01:00
Levi Neely a5b09c73c6
Add upper bound check in check_peer_pubkey() (#323)
Daemon tested, TLS works, crypto folder works
2026-03-03 15:51:54 +01:00
Levi Neely c9bb7685b7
Add POVERLAY_BUFSIZE bounds check in prpc.c read loop (#322)
RPC commands tested, sync list works
2026-03-03 15:49:18 +01:00
Levi Neely 0ae4882ada
Fix integer overflow in prpc.c response->length calculation (#321)
RPC commands tested, daemon works
2026-03-03 15:46:39 +01:00
Levi Neely d0d9ac2d77
Fix ptree_for_each_element loop termination condition (#319)
Daemon tested, starts successfully
2026-03-03 15:29:44 +01:00
Levi Neely ac25de2831
Add integer overflow checks in psync_list_builder_finalize() (#318)
Daemon tested, starts successfully
2026-03-03 15:27:07 +01:00
Levi Neely 00b4824961
Replace sprintf with snprintf in ptools.c (#317)
First login tested, no crash
2026-03-03 15:24:10 +01:00