"Clean room" test for a "copy on write" problem leading to bugs #113
and #928. Under certain conditions a fork()ed child process can write to the parent process' memory. A fix follows... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20401 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6f93ad781b
commit
34ce586692
@ -3,10 +3,17 @@ SubDir HAIKU_TOP src tests system kernel ;
|
||||
UsePrivateHeaders kernel ;
|
||||
UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ;
|
||||
|
||||
SimpleTest cow_bug113_test : cow_bug113_test.cpp ;
|
||||
|
||||
SimpleTest fibo_load_image : fibo_load_image.cpp ;
|
||||
SimpleTest fibo_fork : fibo_fork.cpp ;
|
||||
SimpleTest fibo_exec : fibo_exec.cpp ;
|
||||
|
||||
SimpleTest lock_node_test :
|
||||
lock_node_test.cpp
|
||||
: be
|
||||
;
|
||||
|
||||
SimpleTest port_close_test_1 : port_close_test_1.cpp ;
|
||||
SimpleTest port_close_test_2 : port_close_test_2.cpp ;
|
||||
|
||||
@ -22,16 +29,11 @@ SimpleTest port_wakeup_test_7 : port_wakeup_test_7.cpp ;
|
||||
SimpleTest port_wakeup_test_8 : port_wakeup_test_8.cpp ;
|
||||
SimpleTest port_wakeup_test_9 : port_wakeup_test_9.cpp ;
|
||||
|
||||
SimpleTest transfer_area_test : transfer_area_test.cpp ;
|
||||
|
||||
SimpleTest syscall_time : syscall_time.cpp ;
|
||||
|
||||
SimpleTest yield_test : yield_test.cpp ;
|
||||
SimpleTest transfer_area_test : transfer_area_test.cpp ;
|
||||
|
||||
SimpleTest lock_node_test :
|
||||
lock_node_test.cpp
|
||||
: be
|
||||
;
|
||||
SimpleTest yield_test : yield_test.cpp ;
|
||||
|
||||
SimpleTest wait_test_1 : wait_test_1.c ;
|
||||
SimpleTest wait_test_2 : wait_test_2.cpp ;
|
||||
|
64
src/tests/system/kernel/cow_bug113_test.cpp
Normal file
64
src/tests/system/kernel/cow_bug113_test.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
const char* kInitialValue = "/dev/null";
|
||||
const char* kChangedValue = "Argh!";
|
||||
|
||||
int
|
||||
main(int argc, const char* const* argv)
|
||||
{
|
||||
thread_id parent = find_thread(NULL);
|
||||
|
||||
char* globalVar = NULL;
|
||||
area_id area = create_area("cow test", (void**)&globalVar,
|
||||
B_ANY_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
if (area < 0) {
|
||||
printf("failed to create area\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(globalVar, kInitialValue);
|
||||
|
||||
printf("[%ld] parent: before fork(): globalVar(%p): \"%s\"\n", parent,
|
||||
globalVar, globalVar);
|
||||
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
// child
|
||||
child = find_thread(NULL);
|
||||
|
||||
// let the kernel read access the page
|
||||
struct stat st;
|
||||
stat(globalVar, &st);
|
||||
|
||||
printf("[%ld] child: after kernel read: globalVar: \"%s\"\n",
|
||||
child, globalVar);
|
||||
|
||||
// write access the page from userland
|
||||
strcpy(globalVar, kChangedValue);
|
||||
|
||||
printf("[%ld] child: after change: globalVar: \"%s\"\n", child,
|
||||
globalVar);
|
||||
|
||||
} else {
|
||||
// parent
|
||||
|
||||
// wait for the child
|
||||
status_t exitVal;
|
||||
while (wait_for_thread(child, &exitVal) == B_INTERRUPTED);
|
||||
|
||||
// check the value
|
||||
printf("[%ld] parent: after exit child: globalVar: \"%s\"\n",
|
||||
parent, globalVar);
|
||||
|
||||
if (strcmp(globalVar, kInitialValue) == 0)
|
||||
printf("test OK\n");
|
||||
else
|
||||
printf("test FAILED: child process changed parent's memory!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user