From 58dac744a35129f929b46a41443ee5a3685de5e4 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 11:45:37 +0000 Subject: [PATCH] Fix intermittent VCI signature failure in cart coherency MAM tape_set_cart_coherency() builds the Volume Coherency Information MAM parameter in an uninitialized stack buffer and writes byte 36 (the byte right after the 4-char "LTFS" signature) nowhere. The signature is copied with arch_strncpy(coh_data + 32, "LTFS", 5, 4), which on POSIX is strncpy(dst, "LTFS", 4); since the count equals strlen("LTFS"), no terminating NUL is written, leaving byte 36 as uninitialized stack data. tape_get_cart_coherency() validates the signature with strncmp(coh_data + 32, "LTFS", sizeof("LTFS")), i.e. 5 bytes, so it requires byte 36 to be 0x00. When the leftover stack byte happens to be non-zero, the read-back fails with LTFS12062W, the coherency data for the partition is discarded (LTFS11016W/LTFS11017W), and the next mount falls back to a full medium consistency check. Because the value depends on stack contents at write time, the failure is intermittent. This was introduced in commit 1f1ee3c (#575), which replaced the previous NUL-terminating copy with the 4-byte strncpy. Windows is unaffected because arch_strncpy maps to strncpy_s, which NUL-terminates. Zero the buffer before populating it so byte 36 (and any other gap) is deterministic, restoring a valid signature on the medium. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01PqvvYQzkFL6nNFgbJ9kSuq --- src/libltfs/tape.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libltfs/tape.c b/src/libltfs/tape.c index 255ca2a2..7c294e45 100644 --- a/src/libltfs/tape.c +++ b/src/libltfs/tape.c @@ -1772,6 +1772,17 @@ int tape_set_cart_coherency(struct device_data *dev, const tape_partition_t part CHECK_ARG_NULL(dev, -LTFS_NULL_ARG); CHECK_ARG_NULL(dev->backend, -LTFS_NULL_ARG); + /* Zero the whole buffer so any byte not written explicitly below is + * deterministic. In particular byte 36 (the byte following the 4-char + * "LTFS" signature) is never assigned: arch_strncpy() copies exactly 4 + * bytes and, since the count equals strlen("LTFS"), strncpy() writes no + * terminating NUL on POSIX. Without this memset that byte would carry + * uninitialized stack data onto the medium, and tape_get_cart_coherency() + * compares the signature with sizeof("LTFS") == 5 bytes, so a non-zero + * byte 36 makes the read-back fail (LTFS12062W) and forces a full + * consistency check on the next mount. */ + memset(coh_data, 0, sizeof(coh_data)); + ltfs_u16tobe(coh_data, TC_MAM_PAGE_COHERENCY); coh_data[2] = 0; ltfs_u16tobe(coh_data + 3, TC_MAM_PAGE_COHERENCY_SIZE);