In the lab of Chapter 2, a programming exercise is proposed: add security checks for sys_write
. In this article, we will analyze the security checks and implement them.
The original question is as follows, originally written in Chinese, and I will translate it into English:
In chapter 2, we implemented the first system call sys_write
, which allows us to output information in user mode. However, while the OS provides services, it also has the responsibility to protect itself and other user programs from being compromised by faulty or malicious programs.
Since virtual memory hasn’t been implemented yet, it’s possible to specify a string in a user program that belongs to another program and output it, which is clearly unreasonable. Therefore, we need to add checks to sys_write
:
sys_write
should only be allowed to output data located within the program’s own memory space; otherwise, it should return an error.
Analysis
In the sys_write
function, we need to check whether the buffer is located within the program’s own memory space. We can get the range of the current application and the user stack, then check whether the buffer is located within these two ranges.
Solution
In AppManager
, the n-th application’s memory range is [app_start[n-1], app_start[n])
, and current_app
actually points to the next application. So the current application’s memory range is [app_start[current_app-1], app_start[current_app])
. So we can get the current application’s length by app_start[current_app] - app_start[current_app-1]
. In Batch OS, we load app applications from APP_BASE_ADDRESS
, so the current application’s memory range is [APP_BASE_ADDRESS, APP_BASE_ADDRESS + app_start[current_app] - app_start[current_app-1])
.
In USER_STACK
, we can get the user stack’s top address by USER_STACK.get_sp()
, because the stack grows from high to low in RISC-V, so the user stack’s range is [sp - USER_STACK_SIZE, sp)
.
|
|
When sys_write
is called, we can get the current application’s range and the user stack’s range, then check whether the buffer is located within these two ranges. Don’t forget check the end of the buffer.
By read the test cases code, we should return -1
when the buffer is not located within the current application’s range or the user stack’s range and the file descriptor is not FD_STDOUT
.
|
|
After that, we can run make run TEST=1
to test the implementation. If the test cases is same as the expected results in test cases’ comment, the implementation is correct.
Conclusion
In this article, we analyzed the security checks for sys_write
and implemented them. By checking whether the buffer is located within the current application’s range or the user stack’s range, we can prevent the program from outputting data located in other programs’ memory space. This is a basic security check for system calls, and it’s important to protect the OS and other programs from being compromised by faulty or malicious programs. If you have any questions or suggestions, please feel free to contact me by email or send private messages to me on Matrix.