Skip to content

Fix Integer overflow in binary CPIO handler#5089

Open
sectroyer wants to merge 1 commit into
MidnightCommander:masterfrom
sectroyer:master
Open

Fix Integer overflow in binary CPIO handler#5089
sectroyer wants to merge 1 commit into
MidnightCommander:masterfrom
sectroyer:master

Conversation

@sectroyer
Copy link
Copy Markdown

@sectroyer sectroyer commented Apr 6, 2026

Add a bounds check on st_size immediately after it is computed, before it is used in any arithmetic or allocation. A reasonable upper bound for a symlink target is MC_MAXPATHLEN (4096).

@github-actions github-actions Bot added needs triage Needs triage by maintainers prio: medium Has the potential to affect progress labels Apr 6, 2026
@github-actions github-actions Bot added this to the Future Releases milestone Apr 6, 2026
@zyv zyv modified the milestones: Future Releases, 4.9.0 Apr 6, 2026
@zyv zyv added area: vfs Virtual File System support and removed needs triage Needs triage by maintainers labels Apr 6, 2026
@zyv zyv requested a review from mc-worker April 6, 2026 07:16
Copy link
Copy Markdown
Member

@zyv zyv left a comment

Choose a reason for hiding this comment

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

Thank you for the fix! 👍

@sectroyer sectroyer requested a review from zyv April 15, 2026 16:15
Comment thread src/vfs/cpio/cpio.c Outdated
// case?

inode->linkname = g_malloc (st->st_size + 1);
if (st->st_size < 0 || (gsize) st->st_size >= G_MAXSIZE)
Copy link
Copy Markdown
Contributor

@mc-worker mc-worker Apr 16, 2026

Choose a reason for hiding this comment

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

Why do you reduce off_t to gsize? I think, sizeof (off_t) >= sizeof (gsize), so the correct way is

st->st_size >= (off_t) G_MAXSIZE

Comment thread src/vfs/cpio/cpio.c Outdated
#endif
st.st_size = ((off_t) u.buf.c_filesizes[0] << 16) | u.buf.c_filesizes[1];

if (st.st_size < 0 || st.st_size > MC_MAXPATHLEN)
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.

Why do you compare file size with path length? It is correct for link not for regular file,

Comment thread src/vfs/cpio/cpio.c
u.st.st_size = hd.c_filesize;

if (u.st.st_size < 0 || u.st.st_size > MC_MAXPATHLEN)
{
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.

Likewise.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

You are completely right. I have update the PR w newer fix.

Comment thread src/vfs/cpio/cpio.c Outdated

inode->linkname = g_malloc (st->st_size + 1);
if (st->st_size < 0 || st->st_size >= (off_t) G_MAXSIZE
|| st->st_size > MC_MAXPATHLEN)
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.

MC_MAXPATHLEN is definitely less than G_MAXSIZE. Thus 2nd test isn't needed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@sectroyer I thought this comment was still open. Could you please comment and resolve all remarks which you think are fixed and re-request an approval?

@zyv
Copy link
Copy Markdown
Member

zyv commented May 9, 2026

@sectroyer, are you still planning to do the last fix? I'd like to merge this as soon as master gets unblocked. Thanks!

@sectroyer
Copy link
Copy Markdown
Author

@zyv i would definitely would like this fix to be pushed. Can it be applied directly or are there any issues and you would prefer me to first update pr to git head ?

…ndler

Three changes addressing reviewer feedback:

- cpio_create_entry: fix cast direction in the bounds check —
  compare against (off_t) G_MAXSIZE rather than casting st_size to
  gsize. Also add the MC_MAXPATHLEN upper bound here, co-located with
  the g_malloc call and applied only in the symlink code path where
  st_size is used as a path length.

- cpio_read_bin_head: check only st_size < 0 (catches the signed
  integer overflow root cause). Remove the > MC_MAXPATHLEN bound
  which was too restrictive for non-symlink entries processed by
  this general-purpose function.

- cpio_read_crc_head: same as cpio_read_bin_head.

Signed-off-by: Michał Majchrowicz <sectroyer@gmail.com>
Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
@sectroyer
Copy link
Copy Markdown
Author

Here is a list of changes in push request and replies to comments:
Thread 1 (outdated — (gsize) st->st_size >= G_MAXSIZE):

Fixed in the updated commit — the cast direction is now correct: st->st_size >= (off_t) G_MAXSIZE.

Thread 2 (outdated — st.st_size > MC_MAXPATHLEN in cpio_read_bin_head):

Fixed. The MC_MAXPATHLEN upper bound has been removed from cpio_read_bin_head and cpio_read_crc_head. Those functions handle all entry types, so only the < 0 guard (which catches the
signed overflow root cause) belongs there. The MC_MAXPATHLEN check is now placed exclusively in cpio_create_entry, inside the S_ISLNK branch where st_size is actually used as a path
length.

Thread 3 (Likewise / cpio_read_crc_head — already replied):

Same fix applied — > MC_MAXPATHLEN removed from cpio_read_crc_head.

Thread 4 (new — G_MAXSIZE redundant given MC_MAXPATHLEN):

You are correct — MC_MAXPATHLEN (4096) is far smaller than G_MAXSIZE, making the >= (off_t) G_MAXSIZE check completely redundant. Removed in the latest commit. The guard is now
simply
st->st_size < 0 || st->st_size > MC_MAXPATHLEN.

@zyv I think this resolves all issues ?

@zyv zyv requested a review from mc-worker May 11, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: vfs Virtual File System support prio: medium Has the potential to affect progress

Development

Successfully merging this pull request may close these issues.

Security Issue Report

3 participants