Skip to content

Fix buffer overflow and stack smashing in FileIs* functions during execve - #4426

Open
libx264 wants to merge 4 commits into
ptitSeb:mainfrom
libx264:main
Open

libx264 wants to merge 4 commits into
ptitSeb:mainfrom
libx264:main

Conversation

@libx264

@libx264 libx264 commented Sep 18, 2026

Copy link
Copy Markdown

Summary

Fixes an issue where execve (inside my_execve) crashes with *** buffer overflow detected *** or *** stack smashing detected ***: terminated (SIGABRT) when calling FileIsX64ELF, FileIsX86ELF, FileIsShell, or FileIsPython.

Problem Description

In src/utils/fileutils.c, the file-checking functions used tightly sized stack buffers:

  • char head[20] in FileIsX64ELF, FileIsX86ELF, and FileIsShell
  • char head[25] in FileIsPython

This caused two issues:

  1. Fortify Source false-positives / crashes: When compiled against modern glibc or toolchains with _FORTIFY_SOURCE / __fread_chk enabled, fread(head, size, 1, f) triggered:
    *** buffer overflow detected ***: terminated
    
  2. Stack smashing: When fortify checks were bypassed, reading close to the buffer boundary without safety padding corrupted the stack canary / alignment on ARM64, resulting in:
    *** stack smashing detected ***: terminated
    
  3. In FileIsShell and FileIsPython, strings were read directly to the end of the buffer without leaving room for a trailing \0 null-terminator for subsequent strncmp calls.

Backtrace:

*** buffer overflow detected ***: terminated
[BOX64] NativeBT: libc.so.6(abort+0x28)
[BOX64] NativeBT: libc.so.6(__fread_chk+0x194)
[BOX64] NativeBT: box64() [my_execve helper]
[BOX64] NativeBT: box64(my_execve+0xc8)
[BOX64] EmulatedBT: box64(execve+0)
[BOX64] EmulatedBT: box64-bash(shell_execve+32)

Changes

  • Increased head buffer size to 64 bytes in FileIsX64ELF, FileIsX86ELF, FileIsX64X86ELF, FileIsShell, and FileIsPython.
  • Changed fread call convention from fread(head, size, 1, f) to fread(head, 1, count, f) to prevent buffer overflows and ensure safe bounds.
  • In FileIsShell and FileIsPython, limit reading to sizeof(head) - 1 to guarantee the buffer is always null-terminated.
  • Updated return checks to verify that enough bytes were read (sz < expected_length) rather than strict sz != 1.

Testing

  • Tested on ARM64 with glibc and -fstack-protector-strong.
  • Verified nested execve calls within box64-bash (running commands and subshells) now execute cleanly without triggering fortify or stack corruption.

…nlarge stack buffers to 64 bytes and use safe fread bounds in FileIsX64ELF, FileIsX86ELF, FileIsX64X86ELF, FileIsShell, and FileIsPython. Prevents __fread_chk fortify aborts and stack smashing on ARM64 during execve.
@libx264

libx264 commented Sep 18, 2026

Copy link
Copy Markdown
Author

Should fix #4382

@ptitSeb

ptitSeb commented Sep 18, 2026

Copy link
Copy Markdown
Owner

I'm sorry, but I don't understand were is the fix? the fread change you do is ... strange. The form used in box64 is perfectly legal and correct, so please expand (and please, don't use AI to explain, it's your PR, not an AI one)

Comment thread src/tools/fileutils.c Outdated
Comment thread src/tools/fileutils.c
char head[64] = {0};
size_t sz = fread(head, 1, 20, f);

char head[sizeof(x64lib)] = {0};

@ptitSeb ptitSeb Sep 18, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

what was wrong with the 64-bytes size of the array before, because I think that was the onyl fix there

@libx264 libx264 Sep 18, 2026

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.

I thought it would be good to implement dynamic head buffer size

To reduce the number of magic numbers

Comment thread src/tools/fileutils.c
int sz = fread(head, 20, 1, f);

char head[sizeof(x64lib)] = {0};
int sz = fread(head, sizeof(x64lib) - 1, 1, f);

@ptitSeb ptitSeb Sep 18, 2026

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

x64lib contains a trailling 0 and should be kept in (it's data, not a C string)

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.

Compiler adds an extra 0 on string literals (without -1 it will be 21 instead of 20). Can leave as it or change to unsigned char
ex:
static const unsigned char x64lib[] = {
0x7f, 'E', 'L', 'F', 0x02, 0x01, 0x01, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x00, 0x3e, 0x00
};
in that case sizeof is 20

Comment thread src/tools/fileutils.c
Comment thread src/tools/fileutils.c
Comment thread src/tools/fileutils.c
Comment thread src/tools/fileutils.c
Comment thread src/tools/fileutils.c
int sz = fread(head, SHELL_MAX_LEN - 1, 1, f);
fclose(f);
if(sz < strlen(shsign))
if(sz != 1)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

this is not the same code. sz has a differnt meaning here than in the original code.

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.

Why?

Comment thread src/tools/fileutils.c
Comment thread src/tools/fileutils.c
Comment thread src/tools/fileutils.c
Comment thread src/tools/fileutils.c
@libx264

libx264 commented Sep 18, 2026

Copy link
Copy Markdown
Author

I must apologize, at least for ai description and unnecessary changes. The issue persist on termux, because of patches that change system prefix, but they forgot to modify head size. I should have edited their patch, but I thought it would be good to implement dynamic head buffer size.

@libx264
libx264 marked this pull request as draft September 18, 2026 19:01
@libx264
libx264 marked this pull request as ready for review September 18, 2026 19:49
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