b9874d0941
Add redbear-usb-storage-check in-guest binary that validates USB mass storage read and write I/O: discovers /scheme/disk/ devices, writes a test pattern to sector 2048, reads it back, verifies match, restores original content. Updates test-usb-storage-qemu.sh with write-proof verification step. Includes all accumulated Red Bear OS work: kernel patches, relibc patches, driver infrastructure, DRM/GPU, KDE recipes, firmware, validation tooling, build system hardening, and documentation.
86 lines
2.4 KiB
C
86 lines
2.4 KiB
C
#include <signal.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <sys/ptrace.h>
|
|
#include <sys/user.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include "test_helpers.h"
|
|
|
|
#ifdef __linux__
|
|
|
|
#define SYS_write 1
|
|
|
|
#endif
|
|
#ifdef __redox__
|
|
|
|
#define SYS_write 0x21000004
|
|
|
|
#endif
|
|
|
|
int main() {
|
|
int pid = fork();
|
|
ERROR_IF(fork, pid, == -1);
|
|
|
|
if (pid == 0) {
|
|
// Test behavior on Redox when TRACEME hasn't been activated
|
|
// before waitpid is invoked!
|
|
usleep(100000);
|
|
|
|
int result = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
|
|
ERROR_IF(ptrace, result, == -1);
|
|
UNEXP_IF(ptrace, result, != 0);
|
|
|
|
// Alert parent: I'm ready
|
|
result = raise(SIGSTOP);
|
|
ERROR_IF(raise, result, == -1);
|
|
UNEXP_IF(raise, result, != 0);
|
|
|
|
puts("This is printed to STDOUT.");
|
|
puts("Or, at least, that's what I thought.");
|
|
puts("But all write(...) syscalls are actually redirected to STDERR by the tracer.");
|
|
puts("Big surprise, right!");
|
|
} else {
|
|
// Wait for child process to be ready
|
|
int result = waitpid(pid, NULL, 0);
|
|
ERROR_IF(waitpid, result, == -1);
|
|
|
|
int status;
|
|
while (true) {
|
|
// puts("----- Pre-syscall -----");
|
|
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
|
|
ERROR_IF(ptrace, result, == -1);
|
|
UNEXP_IF(ptrace, result, != 0);
|
|
// puts("Wait...");
|
|
result = waitpid(pid, &status, 0);
|
|
ERROR_IF(waitpid, result, == -1);
|
|
if (WIFEXITED(status))
|
|
break;
|
|
|
|
struct user_regs_struct regs;
|
|
// puts("Get regs");
|
|
result = ptrace(PTRACE_GETREGS, pid, NULL, ®s);
|
|
ERROR_IF(ptrace, result, == -1);
|
|
|
|
if (regs.orig_rax == SYS_write || regs.orig_rax == SYS_write) {
|
|
regs.rdi = 2;
|
|
puts("Set regs");
|
|
result = ptrace(PTRACE_SETREGS, pid, NULL, ®s);
|
|
ERROR_IF(ptrace, result, == -1);
|
|
}
|
|
|
|
// puts("Post-syscall");
|
|
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
|
|
ERROR_IF(ptrace, result, == -1);
|
|
UNEXP_IF(ptrace, result, != 0);
|
|
// puts("Wait...");
|
|
result = waitpid(pid, &status, 0);
|
|
ERROR_IF(waitpid, result, == -1);
|
|
if (WIFEXITED(status))
|
|
break;
|
|
}
|
|
printf("Child exited with status %d\n", WEXITSTATUS(status));
|
|
}
|
|
}
|