Category Archives: _Deep Dive ๐Ÿ”

Linux Internals: How /proc/self/mem writes to unwritable memory

Introduction

An obscure quirk of the /proc/*/mem pseudofile is its โ€œpunch throughโ€ semantics. Writes performed through this file will succeed even if the destination virtual memory is marked unwritable. In fact, this behavior is intentional and actively used by projects such as the Julia JIT compiler and rr debugger.

This behavior raises some questions: Is privileged code subject to virtual memory permissions? In general, to what degree can the hardware inhibit kernel memory access?

By exploring these questions1, this article will shed light on the nuanced relationship between an operating system and the hardware it runs on. We’ll examine the constraints the CPU can impose on the kernel, and how the kernel can bypass these constraints.

Continue reading

Open source licensing for supervillains

This post covers my research into open source software licensing and my analysis of real-world open source projects that profit off of open source code via proprietary licenses.

Keep reading and you’ll learn:

  • What the difference between a restrictive and permissive license is
  • What dual licensing is and how you can use it make money off of open source code
  • What CLAs are and the specific clause your CLA needs for use with dual licensing
  • Examples of companies that implement dual licensing and how they do it

And of course: I am not a lawyer and none of this is legal advice.


Let’s talk evil. And by evil, I mean money.

Continue reading

What they don’t tell you about demand paging in school

This post details my adventures with the Linux virtual memory subsystem, and my discovery of a creative way to taunt the OOM (out of memory) killer by accumulating memory in the kernel, rather than in userspace.

Keep reading and you’ll learn:

  • Internal details of the Linux kernel’s demand paging implementation
  • How to exploit virtual memory to implement highly efficient sparse data structures
  • What page tables are and how to calculate the memory overhead incurred by them
  • A cute way to get killed by the OOM killer while appearing to consume very little memory (great for parties)

Note: Victor Michel wrote a great follow up to this post here.

Continue reading

How setjmp and longjmp work (2016)

Pretty recently I learned about setjmp() and longjmp(). Theyโ€™re a neat pair of libc functions which allow you to save your programโ€™s current execution context and resume it at an arbitrary point in the future (with some caveats1). If youโ€™re wondering why this is particularly useful, to quote the manpage, one of their main use cases is โ€œโ€ฆfor dealing with errors and interrupts encountered in a low-level subroutine of a program.โ€ These functions can be used for more sophisticated error handling than simple error code return values.

I was curious how these functions worked, so I decided to take a look at musl libcโ€™s implementation for x86. First, Iโ€™ll explain their interfaces and show an example usage program. Next, since this post isnโ€™t aimed at the assembly wizard, Iโ€™ll cover some basics of x86 and Linux calling convention to provide some required background knowledge. Lastly, Iโ€™ll walk through the source, line by line.

Continue reading