-
Notifications
You must be signed in to change notification settings - Fork 24
Open
Description
Describe the bug
The kernel panics with an attempt to add with overflow error when the pread system call is invoked with a negative offset (specifically (off_t)-1). This occurs in the axfs_ramfs module.
ruxos/crates/axfs_ramfs/src/file.rs
Line 64 in 32a8fe8
| let end = content.len().min(offset as usize + buf.len()); |
To Reproduce
- Compile the program and run.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <stdint.h>
/*
* PoC for potential remainder by zero in RuxOS ext4 filesystem
*
* The crash occurs in ruxfs/src/fs/ext4_rs.rs:43 in the read_offset function:
* let mut offset_in_block = offset % DISK_BLOCK_SIZE;
*
* While DISK_BLOCK_SIZE is a constant (512), the static analyzer flags this as
* a potential division by zero. This PoC attempts to trigger the condition
* by performing file operations with various offsets.
*
* Reachability analysis:
* - The read_offset function is part of BlockDevice trait implementation
* - It's called during file read operations through the filesystem layer
* - User applications can trigger this via open(), read(), lseek() syscalls
* - The offset parameter is controllable from user space
*
* Note: In practice, DISK_BLOCK_SIZE is a constant (512), so actual division
* by zero shouldn't occur. This is likely a false positive from static analysis.
*/
int main() {
const char* filename = "/tmp/test_file";
int fd;
char buffer[4096];
ssize_t bytes_read;
// Create a test file
fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, 0644);
if (fd < 0) {
perror("open");
return 1;
}
// Write some data to the file
const char* data = "This is test data for triggering the potential remainder by zero issue";
write(fd, data, strlen(data));
// Attempt to read at various offsets to trigger the condition
// The offset parameter in read_offset comes from file position
off_t test_offsets[] = {
0, // Normal case
511, // Just before block boundary
512, // Exactly at block boundary
1023, // Near next block boundary
1024, // At next block boundary
4095, // Large offset
4096, // Block size boundary
8192, // Multiple blocks
(off_t)-1, // Negative offset (should fail but worth trying)
SIZE_MAX - 511 // Very large offset
};
int num_tests = sizeof(test_offsets) / sizeof(test_offsets[0]);
for (int i = 0; i < num_tests; i++) {
printf("Testing offset: %ld\n", test_offsets[i]);
// Seek to the test offset
if (lseek(fd, test_offsets[i], SEEK_SET) == (off_t)-1) {
printf(" lseek failed for offset %ld\n", test_offsets[i]);
continue;
}
// Attempt to read - this should trigger read_offset in the kernel
bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read < 0) {
printf(" read failed for offset %ld\n", test_offsets[i]);
} else {
printf(" Successfully read %zd bytes at offset %ld\n", bytes_read, test_offsets[i]);
}
}
// Additional test: Use pread to read at specific offsets without changing file position
printf("\nTesting with pread:\n");
for (int i = 0; i < num_tests; i++) {
printf("Testing pread at offset: %ld\n", test_offsets[i]);
bytes_read = pread(fd, buffer, sizeof(buffer), test_offsets[i]);
if (bytes_read < 0) {
printf(" pread failed for offset %ld\n", test_offsets[i]);
} else {
printf(" Successfully pread %zd bytes at offset %ld\n", bytes_read, test_offsets[i]);
}
}
close(fd);
unlink(filename);
printf("\nPoC completed. If the kernel has the remainder by zero vulnerability, "
"it should have panicked during one of the read operations.\n");
return 0;
}
2.features.txt
alloc
paging
net
multitask
irq
fs
Environment
Logs
SeaBIOS (version 1.16.3-debian-1.16.3-2)
iPXE (https://ipxe.org) 00:03.0 CA00 PCI2.10 PnP PMM+7EFCAA40+7EF0AA40 CA00
Booting from ROM..
Initialize IDT & GDT...
8888888b. .d88888b. .d8888b.
888 Y88b d88P" "Y88b d88P Y88b
888 888 888 888 Y88b.
888 d88P 888 888 888 888 888 888 "Y888b.
8888888P" 888 888 `Y8bd8P' 888 888 "Y88b.
888 T88b 888 888 X88K 888 888 "888
888 T88b Y88b 888 .d8""8b. Y88b. .d88P Y88b d88P
888 T88b "Y88888 888 888 "Y88888P" "Y8888P"
arch = x86_64
platform = x86_64-qemu-q35
target = x86_64-unknown-none
smp = 1
build_mode = debug
log_level = warn
[ 0.191208 0 axfs_ramfs::dir:68] AlreadyExists sys
Testing offset: 0
Successfully read 70 bytes at offset 0
Testing offset: 511
Successfully read 0 bytes at offset 511
Testing offset: 512
Successfully read 0 bytes at offset 512
Testing offset: 1023
Successfully read 0 bytes at offset 1023
Testing offset: 1024
Successfully read 0 bytes at offset 1024
Testing offset: 4095
Successfully read 0 bytes at offset 4095
Testing offset: 4096
Successfully read 0 bytes at offset 4096
Testing offset: 8192
Successfully read 0 bytes at offset 8192
Testing offset: -1
lseek failed for offset -1
Testing offset: -512
lseek failed for offset -512
Testing with pread:
Testing pread at offset: 0
Successfully pread 70 bytes at offset 0
Testing pread at offset: 511
Successfully pread 0 bytes at offset 511
Testing pread at offset: 512
Successfully pread 0 bytes at offset 512
Testing pread at offset: 1023
Successfully pread 0 bytes at offset 1023
Testing pread at offset: 1024
Successfully pread 0 bytes at offset 1024
Testing pread at offset: 4095
Successfully pread 0 bytes at offset 4095
Testing pread at offset: 4096
Successfully pread 0 bytes at offset 4096
Testing pread at offset: 8192
Successfully pread 0 bytes at offset 8192
Testing pread at offset: -1
[ 0.198242 0:1 ruxruntime::lang_items:14] panicked at crates/axfs_ramfs/src/file.rs:64:37:
attempt to add with overflow
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels