
trying hard. streaming kernel dev - https://xitter.cf/t.co/aO5X4jXGQD blogging about life, art & systems programming. non-expert work: @ableton, ex @trailofbits
berlin • he
Joined March 2011
- Tweets5.8K
- Following1.6K
- Followers7.3K
- Likes7.8K
Pinned Tweet
New kernel post! This time: /proc/*/mem and how it writes to unwritable mem.
Key takeaway: By walking page tables in software, the kernel can access userspace mem without directly dereferencing pointers it gets from userspace. (No WP/SMAP bits involved). offlinemark.com/2021/05/12/a…
week 140, streaming kernel dev (c++)
topic: virtual memory
short stream, was mostly investigating whether I can replace a memset with brace C++ object construction
(as you might expect, the answer was no, the C++ rules are way too brittle/fragile here 😂)
link + recap ↓
ERRATA:
I'll revise my statement - I think it is totally possibly C++ brace object construction to replace my page table memset, but I still am unconvinced to really do it that way
My confusion came from accidentally using parens () instead of braces {} in my placement new (which would replace the memset)
This situation then involves a double memset because of the complex C++ construction rules
Using {} works, but is brittle, somewhat error prone, and doesn't convey intent well (which were my original points against it)
So I still don't know if I'd ship it in production, since memset() conveys intent very well and just works. But it is possible
learn Linux kernel exploitation from one of the best 👇
We finally got this series out. We tried to simplify Linux kernel exploitation for those interested in getting started. There are plenty of resources out there, but my impression is that they are written for experienced people, not for beginners in this complex field.
In this series, we tried to do something close to real-world kernel exploitation, but much simpler, so people can use it as a first contact with Linux kernel exploitation. I hope people like it, and we will be available to help anyone who wants to reproduce all the content.
week 139, streaming kernel dev (c++)
topic: virtual memory
this was just a small refactoring stream - tweaking and refining some of my virtual memory/paging code
link + recap ↓
the only thing really worth mentioning here is that I use templates pretty liberally through my VM code
TBD on whether this is worth it, but it allows me to use a generic struct GenericPageTable, for operations that are in common amongst the different levels
while having different struct types to represent e.g. Page table entries, from Pml4 Table entries, from Page directory entries.
everything you ever wanted to know about bitmaps
New linux-insides chapter is out!
Continue to investigate different data structures and how they are implemented in the Linux kernel.
This time: Bitmaps in the Linux kernel 0xax.dev/books/linux-inside/…
week 138, streaming kernel dev (c++)
topic: using musl libc in kernel
short prerecorded stream about how I use musl libc in my kernel. picolibc might be a better choice but this works well too
link + recap ↓
originally I inherited hand rolled memcpy etc from JOS but I’ve been trying to reduce my first party code surface, and in general want to use third party libs when possible
musl libc is pretty minimal and works ok for this purpose. I don’t actually a build a full musl since that’s a hosted libc for userspace but I’m able to extract just the routines I want and vendor them, and integrate them into the build system
there is a bit of build time header generation that I needed reimplement since I’m not using the musl build system but ai was helpful for that
I’m very happy with this approach and the fact that I don’t need to write my own memcpy lol
week 137, streaming kernel dev (c++)
topic: preemptive multitasking
Now that the timer interrupt is working, I added a basic preemptive multitasking impl. Since cooperative yields are already working, this was pretty trivial, just call yield from the interrupt handler
link + recap ↓
Calling taskYield() from the timer interrupt handler was enough to implement a basic form of preemptive multitasking
The task’s state is preserved at that point in the interrupt handler, and then when it gets execution again, it finishes the interrupt handler and irets back into the task
The important part was just to call yield after acknowledging the interrupt, otherwise we’d schedule out and no other interrupts would happen
To be clear, this isn’t the final implementation. In general it’s not good to schedule in an interrupt handler, so we might need to add some kind of “need_sched” flag and then schedule at the very end of the interrupt return path
It’s also interesting to compare my implementation with @nsg650’s - after selecting a next task, he opts to overwrite the trap frame on the stack with the new task’s, and use the iret as the mechanism to switch tasks
This is different from my way of context switching entirely in software using plain ret
After getting it working, I used this as an opportunity to test out my in-kernel integration test framework, and wrote an integration test
I created two tasks, which each receive a pointer to a bool. The first task spins, and then checks that the bool is marked true. The second task simply marks the bool as true. This checks that the second task got CPU time without the first task explicitly yielding
One tricky part was adding this test without disrupting the other integration tests which aren’t designed to run with a timer interrupt. I added a hacky config mechanism for this so those tests can run without a timer interrupt, but that will need some future work
week 136, streaming kernel dev (c++)
topic: LAPIC timer
After getting the timer interrupt working last week, I did some refactoring. I decided to make the interrupt handlers static member functions on the LocalApic driver class
link + recap ↓
Last week I got the timer interrupt working, but only with some hacky code
I moved the timer interrupt handler functions into the LocalApic driver class to co-locate the code closer
I had to make them static member functions because my interrupt dispatch code uses a function pointer table
This was a little inconvenient because in the member functions, we can’t just call the eoi() method for example, but need to relocate the LocalApic driver via the Kernel reference that’s passed
I thought of trying to use a regular member functions, but it’s complex ABI-wise to store pointers to those, so I didn’t go with that approach
I also experimented with with an API for letting the LocalApic dynamically register its interrupt handlers in the constructor, instead of statically hardcoding them in the Idt definition
But decided against that, since the dynamic flexibility isn’t currently needed, and the code is less understandable that way
week 135, streaming kernel dev (c++)
topic: timer interrupt
got the LAPIC timer interrupt working!! the LAPIC is a complex device, but it turns out it's not so bad to configure it for a simple timer. wired that into my interrupt subsystem and it's working =)
link + screenshots ↓
last week i got the basics set up to do MMIO accesses to the LAPIC, but that was it
I cleaned up the design and created an MmioWrapper abstraction for conveniently doing MMIO accesses, using templates
The idea is that driver classes will take one of these on construction, meaning the responsibility for mapping the device lives outside the driver. I created a factory function to do this and construct the Local Apic driver class
Then it was a matter of doing the right LAPIC configs, which were:
- Spurious Interrupt Vector Register -> Write to this to enable the LAPIC in general, and also set the Spurious Interrupt Vector number
(Funny how such an important enable bit is hidden in this very exotic register)
- Set the divisor offset
- Set the timer to periodic mode (instead of one-shot) and also register the Timer Interrupt Vector number (this is the important part!)
- Set an initial count of the timer
Then I registered interrupt handles for these new interrupt vectors and was able to it getting called regularly =)
























