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
38 changes: 35 additions & 3 deletions src/libltfs/tape.c
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,13 @@ int tape_get_volume_change_reference(struct device_data *dev, uint64_t *volume_c
int ret;
unsigned char vcr_data[TC_MAM_PAGE_VCR_SIZE + TC_MAM_PAGE_HEADER_SIZE];

/* The VCR is read as a 32-bit field at offset 5 (just past the page
* header), so the buffer must hold at least 5 + 4 bytes. Lock that at
* compile time so a change to the page-size constants cannot make the
* read below run off the end of the buffer. */
_Static_assert(sizeof(vcr_data) >= 5 + sizeof(uint32_t),
"MAM VCR page too small to hold the volume change reference");

CHECK_ARG_NULL(dev, -LTFS_NULL_ARG);
CHECK_ARG_NULL(dev->backend, -LTFS_NULL_ARG);

Expand Down Expand Up @@ -1741,7 +1748,8 @@ int tape_get_cart_coherency(struct device_data *dev, const tape_partition_t part
if (ap_clent_specific_len != 42 && ap_clent_specific_len != 43) {
ltfsmsg(LTFS_WARN, 12061W, ap_clent_specific_len);
return -LTFS_UNEXPECTED_VALUE;
} else if (strncmp((char *)coh_data + 32, "LTFS", sizeof("LTFS")) != 0) {
} else if (strncmp((char *)coh_data + 32, TC_MAM_COHERENCY_SIGNATURE,
sizeof(TC_MAM_COHERENCY_SIGNATURE)) != 0) {
ltfsmsg(LTFS_WARN, 12062W);
return -LTFS_UNEXPECTED_VALUE;
}
Expand Down Expand Up @@ -1769,6 +1777,18 @@ int tape_set_cart_coherency(struct device_data *dev, const tape_partition_t part
int ret;
unsigned char coh_data[TC_MAM_PAGE_COHERENCY_SIZE + TC_MAM_PAGE_HEADER_SIZE];

/* The coherency record is written below at fixed byte offsets; the version
* byte at offset 74 is the highest, so the page must be at least 75 bytes.
* Lock that invariant at compile time so a future change to the page-size
* constants cannot silently overflow this stack buffer. */
_Static_assert(sizeof(coh_data) > 74,
"MAM coherency page too small for the coherency record layout");

/* Zero unwritten bytes for deterministic on-medium content. The "LTFS"
* signature's NUL terminator is written explicitly below, so correctness of
* the signature no longer depends on this memset. */
memset(coh_data, 0, sizeof(coh_data));

CHECK_ARG_NULL(dev, -LTFS_NULL_ARG);
CHECK_ARG_NULL(dev->backend, -LTFS_NULL_ARG);

Expand All @@ -1782,8 +1802,13 @@ int tape_set_cart_coherency(struct device_data *dev, const tape_partition_t part
/* APPLICATION CLIENT SPECIFIC INFORMATION LENGTH */
coh_data[30] = 0; /* Size of APPLICATION CLIENT SPECIFIC INFORMATION (Byte 1) */
coh_data[31] = 43; /* Size of APPLICATION CLIENT SPECIFIC INFORMATION (Byte 0) */
/* Size of the buffer to insert 'LTFS' needs to be size of 5 for the 4 letters and the null terminator*/
arch_strncpy((char *)coh_data + 32,"LTFS", 5, 4);
/* Volume coherency signature: the 4 letters "LTFS" plus a trailing NUL at
* offset 36. The reader compares all 5 bytes, so copy the NUL terminator
* explicitly (an earlier strncpy-based write copied only 4 bytes and left
* byte 36 uninitialised, triggering a full consistency check on every mount). */
_Static_assert(sizeof(TC_MAM_COHERENCY_SIGNATURE) == 5,
"LTFS coherency signature must be 4 characters plus a NUL terminator");
memcpy(coh_data + 32, TC_MAM_COHERENCY_SIGNATURE, sizeof(TC_MAM_COHERENCY_SIGNATURE));
memcpy(coh_data + 37, coh->uuid, 37);
/*
Version field
Expand All @@ -1803,6 +1828,13 @@ int tape_get_cart_volume_lock_status(struct device_data *dev, int *status)
int ret;
unsigned char attr_data[TC_MAM_LOCKED_MAM_SIZE + TC_MAM_PAGE_HEADER_SIZE];

/* The lock status byte is read at offset TC_MAM_PAGE_HEADER_SIZE, so the
* buffer must extend past the page header. Lock that at compile time so a
* change to the page-size constants cannot make the read below run off the
* end of the buffer. */
_Static_assert(sizeof(attr_data) > TC_MAM_PAGE_HEADER_SIZE,
"MAM locked-MAM page too small to hold the lock status byte");

CHECK_ARG_NULL(dev, -LTFS_NULL_ARG);
CHECK_ARG_NULL(status, -LTFS_NULL_ARG);

Expand Down
1 change: 1 addition & 0 deletions src/libltfs/tape_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ typedef enum {
#define TC_MAM_PAGE_VCR_SIZE (0x4) /* Size of Volume Change Reference */
#define TC_MAM_PAGE_COHERENCY (0x080C)
#define TC_MAM_PAGE_COHERENCY_SIZE (0x46)
#define TC_MAM_COHERENCY_SIGNATURE "LTFS" /* Volume coherency signature; 4 chars + NUL, reader compares all 5 */

#define TC_MAM_APP_VENDER (0x0800)
#define TC_MAM_APP_VENDER_SIZE (0x8)
Expand Down