This Month in Rust OSDev: August 2022
Welcome to a new issue of "This Month in Rust OSDev". In these posts, we give a regular overview of notable changes in the Rust operating system development ecosystem.
This series is openly developed on GitHub. Feel free to open pull requests there with content you would like to see in the next issue. If you find some issues on this page, please report them by creating an issue or using our comment form at the bottom of this page.
In this section, we give an overview of notable changes to the projects hosted under the
uefi crate provides safe and performant wrappers for UEFI, the successor to the BIOS.
We merged the following changes in August:
- Added macros
doc_auto_cfgto show feature requirements on docs.rs
- QEMU/OVMF improvements
nixrequirement from 0.24.1 to 0.25.0
- Update deprecation version in
- Relax version requirements for various deps
We also published a subset of the above changes as a new
bootloader crate implements a custom Rust-based bootloader for easy loading of 64-bit ELF executables.
This month, we finally finished the new BIOS boot implementation for the upcoming
v0.11 release. It's now almost completely written in Rust (instead of assembly), which should make further improvements much easier.
Some selected commits that might be interesting:
- Load a third stage
- Load the kernel into buffer memory
- Copy kernel to protected mode
- Jump to third stage
- Set up paging and enter long mode (compatibility mode)
- Create prototype for long mode stage 4 and load it
- Load long mode
GDTand jump to 4th stage
- Query vesa modes and filter by resolution
- Enable VESA framebuffer and update screen writer in stages 3 and 4
E820memory map and put everything together
All the tests are passing now, so we only need to do some cleanup and write proper documentation, then we should be ready to publish an alpha release for testing.
linked-list-allocator crate provides a basic
no_std allocator that builds a linked list from freed memory blocks and thus needs no additional data structures.
In August, Evan Richter discovered a vulnerability in
Heap::extend that could lead to out-of-bound writes. The issue occurred when
extend was called with a size smaller than
size_of::<usize> * 2, i.e., a size too small to store the metadata for the new memory region.
Upon investigating this issue, we found several similar issues:
- Initializing a heap with a size smaller than
size_of::<usize> * 3could result in an out-of-bounds write too.
extendon an uninitialized heap could also result in an out-of-bounds write.
extendon a heap whose size is not a multiple of the size of two
usizes resulted in unaligned writes.
We created a security advisory with more details and released a fix in
v0.10.2, with the following changes:
- The initialization functions now panic if the given size is not large enough to store the necessary metadata. Depending on the alignment of the heap bottom pointer, the minimum size is between
2 * size_of::<usize>and
3 * size_of::<usize>.
extendmethod now panics when trying to extend an unitialized heap.
- Extend calls with a size smaller than
size_of::<usize>() * 2are now buffered internally and not added to the list directly. The buffered region will be merged with future
size()method now returns the usable size of the heap, which might be slightly smaller than the
top() - bottom()difference because of alignment constraints.
Thanks to @evanrichter for reporting this vulnerability and working with us on a fix.
Maintained by @toku-sa-n
xhci crate provides types of xHCI structures, such as Registers and TRBs.
We merged the following changes this month:
- Allow updating single fields of InterrupterRegisterSet (published as
Thanks to @Demindiro for their contribution!
Maintained by @IsaacWoods
pci_types library provides types for accessing and configuring PCI devices from Rust operating systems.
We merged the following change in August:
Thanks to @0Killian for this contribution!
acpi repository contains crates for parsing the ACPI tables – data structures that the firmware of modern computers use to relay information about the hardware to the OS.
We merged the following changes this month:
Call for Participation
Want to contribute to a Rust OSDev project, but don't know where to start? Help with one of these outstanding issues!
If you maintain a Rust project related to operating system development and are looking for contributors, especially for tasks suited to people getting started in this space, please create a PR against the
next branch with the tasks you want to include in the next issue.
In this section, we describe updates to Rust OS projects that are not directly related to the
rust-osdev organization. Feel free to create a pull request with the updates of your OS project for the next post.
(Section written by @drzewiec)
It's been a while since my last project update! That's partly because life has been busy, but also because this update concerns a huge feature. I'm very pleased to report that I have been able to add preemptive multitasking to CelOS.
This was feature that took a good bit of foundation to be able to implement (hence why it took me so long). I had to spend a good bit of time getting memory allocation (both physical and virtual) into a happier place, as well as add support for ACPI and the APIC. And, of course, there were many snags along the way as I learned (at least some of) the traps that are easy to step into when doing something as delicate as context switching.
Now that I have finished this key feature, I plan to work on setting up the other infrastructure needed to begin writing services in userspace (such as message passing and synchronization primitives). And, hopefully soon, finally make the jump into ring 3!
As always, many thanks to @phil-opp for his hard work on supporting the Rust osdev community, and for writing the apic crate which helped serve as a sanity check while I wrote my own driver for the IOAPIC and LAPIC. Thanks as well to the maintainers of the excellent acpi crate, you guys are doing incredible work out there!
Blog Post: GNU ld Discards Section Containing Code – Section Flags in Assembly are Important
(Section written by @phip1611)
In late August/early September, I encountered problems when building my Rust kernel. I faced
unintuitive interaction between my global assembly code and the linker. I specified a custom
section in assembly with executable code with
.section .bootcode. The linker never linked
the code where I specified it in my linker script. It's address was not what it is supposed to be.
readelf didn't show the section inside the binary either. The section was discarded no matter
how hard I tried to modify the linker, thus,
KEEP((.bootcode)); also didn't work. An experienced
colleague ensured me that my linker script is correct.
Section names such as
.text.bootcode worked by the way. Only my custom name was
rejected somehow. In the end, I figured out writing
.section .bootcode, "ax" does the trick. The
difference is small, but the impact to the object file and final executable of those section flags
is big. I could find the answer in the ELF specification. A section needs to be allocatable
a-flag) so that it can be properly placed in a LOAD segment/program header. The section names
.text.* have this pre-configured but my custom section name
.bootcode has not.
(Section written by @phil-opp)
We also received multiple pull requests to add and update translations:
- Fix Japanese translation of "Double Faults"
- Update the chinese translation
- [Translation][Korean] post-04
We are still looking for reviewers for the last two PRs. If you speak Chinese or Korean, it would be great if you could take a look!
Are you interested in Rust-based operating system development? Our
rust-osdev organization is always open to new members and new projects. Just let us know if you want to join! A good way for getting in touch is our gitter channel.