Skip to content

Memory-safety fixes: uninitialized reads and a realloc leak - #613

Open
matejk wants to merge 2 commits into
LinearTapeFileSystem:mainfrom
matejk:fix/memory-safety
Open

Memory-safety fixes: uninitialized reads and a realloc leak#613
matejk wants to merge 2 commits into
LinearTapeFileSystem:mainfrom
matejk:fix/memory-safety

Conversation

@matejk

@matejk matejk commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Two commits:

  • Reads of uninitialized values on error paths (4 sites): tape_get_pews leaves *pews unset on -LTFS_UNSUPPORTED while the caller computes pews + 10; ltfs_profiler_set tested an unset ret when the volume had neither an iosched nor a device handle; _get_dump derived a transfer length from cap_buf without checking the READ BUFFER result; the ICU normalize callers compared the output pointer against the input before checking the return code, reading uninitialized memory and potentially leaking the input buffer.
  • Key-list leak in the simple KMI: realloc was assigned straight back to priv.dk_list, so a failure overwrote the only pointer to the existing buffer with NULL and leaked it.

@vandelvan
vandelvan requested review from XV02, madjesc and syaoraang June 12, 2026 20:55
matejk added 2 commits June 17, 2026 22:06
Four sites used a value that may never have been set:
- tape_get_pews leaves *pews unset on -LTFS_UNSUPPORTED, which the
  caller treats as non-fatal before computing pews + 10.
- ltfs_profiler_set left ret unset when the volume had neither an
  iosched nor a device handle, then tested it.
- _get_dump derived a transfer length from cap_buf without checking
  the READ BUFFER result, so a failed read produced a garbage length.
- the ICU normalize helpers leave their output pointer unset on error,
  but the callers compared that pointer against the input (to decide
  whether to free a no-op result) before checking the return code,
  reading uninitialized memory and potentially leaking the input
  buffer.

Initialize pews and ret, check the READ BUFFER result, and check the
normalize return code before the pointer comparison in all five
callers.
realloc was assigned back to priv.dk_list, so a failure overwrote the
only pointer to the existing buffer with NULL and leaked it. Use a
temporary and free the original on failure.
@matejk
matejk force-pushed the fix/memory-safety branch from 1c27543 to 418c898 Compare June 17, 2026 20:35

@XV02 XV02 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all your work, just some correctness comments :DD

Comment thread src/kmi/simple.c
Comment on lines +195 to +208
if (priv.dk_list) {
unsigned char *expanded = (unsigned char*)realloc(priv.dk_list, dk_list_len);
if (expanded == NULL) {
ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__);
free(priv.dk_list);
return -LTFS_NO_MEMORY;
}
priv.dk_list = expanded;
} else {
priv.dk_list = (unsigned char*)calloc(dk_list_len, sizeof(unsigned char));
if (priv.dk_list == NULL) {
ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__);
return -LTFS_NO_MEMORY;
if (priv.dk_list == NULL) {
ltfsmsg(LTFS_ERR, 10001E, __FUNCTION__);
return -LTFS_NO_MEMORY;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change seems to add more unnecessary complexity and repeated code. Maybe adding the brackets for clarity can be a good change. The added free on the original error path should be enough.

Comment thread src/libltfs/ltfs.c
Comment on lines +4407 to +4408
/* ret stays unset if neither the iosched nor device handle is present;
* the final "if (!ret && ret_save)" would then read garbage. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is out of scope for documentation, there's no need to over explain the initialization of the variable. Was this AI generated?

Comment thread src/libltfs/pathname.c
Comment on lines +201 to +202
/* icu_nfd is unset on error; free the input and bail before
* comparing the (garbage) output pointer. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto about the comment.

Comment thread src/libltfs/pathname.c
Comment on lines +225 to +226
/* *new_name is unset on error; free the input and bail before
* comparing the (garbage) output pointer. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto about the comment.

Comment thread src/libltfs/tape.c
Comment on lines +376 to +378
/* tape_get_pews leaves this unset when it returns -LTFS_UNSUPPORTED,
* which the caller treats as non-fatal and then reads pews; default to 0
* so the fallback (pews + 10) is deterministic. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto about the comment.

Comment on lines +316 to +317
/* cap_buf is indeterminate on failure; do not derive a transfer
* length from it. */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto about the comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants