35C3: Safe And Secure Drivers In High-Level Languages

Writing device drivers is always a good start for a journey into the Linux kernel code. Of course, the kernel is a highly complex piece of software, and if you mess up your code properly, you might take down the entire system with you. User-space drivers on the other hand might not look as good on your CV, but they can help to work around some of the dangers and complexity of the kernel space. Plus, you don’t necessarily have to limit yourself to C to write them, especially if you are concerned about the usual C pitfalls and the security issues they can lead to.

With that in mind, [Paul Emmerich] is researching the concept of Linux user-space drivers for Intel’s 10Gbit network cards using other high-level languages, and recruits his students to write their final theses about the implementation details of as many languages as possible.

At last year’s 34c3, [Paul] already demonstrated the basics of writing such a user-space network driver for Linux, which serves now as reference implementation for his students. We won’t see Bash or JavaScript here, but we will see a brief summary of what it generally means to develop user-space drivers in C#, Swift, OCaml, or Haskell, along a more detailed insight from [Sebastian Voit] and [Simon Ellmann] about Go and Rust. A collection of each language’s implementation can be found on GitHub.

Since some of these languages bring their own memory handling and perform unpredictable garbage collection, performance and latency are two big topics to cover here. But then, the general concept is language-independent, so even if nothing in the world could ever make you give up on C, you might at least take away some new ideas for driver development.

12 thoughts on “35C3: Safe And Secure Drivers In High-Level Languages

  1. Why do they all have the same face?

    Aside from that, I like the idea. For drivers specifically and low-level code in general, it’s basically an unmanageable task to consistently write secure code by hand. While high-level languages aren’t necessarily the only solution, they do automatically manage code which could cause security holes, which is nice.

    1. same face? they all look alike to you? uhhh.. ;)

      btw, happy 0x7e3 everyone.

      (at first, I wasn’t sure if 35c3 was something to do with 2019. clearly, it does not.)

      I suggest that for jan-1-2019 (only), all articles should be tagged with 0x7e3, just for fun.

          1. Well, it’s in decimal not hex, and you have the two halves backwards.
            But after the 255th C3 conference comes the 256th one :P
            Although since this is their 3rd naming scheme (at least that I’m aware of), after 200+ years it will likely be written out differently, assuming it still exists.

    1. I think with some kernel support for managing the ring buffer the performance hit would be small. We used userspace drivers for a WiFi chip we were testing (via libusb) and the performance was certainly useable, without any effort at optimisation.

      1. By processing the buffers in userspace, you can’t take advantage of the extensive mechanisms for zero-copy buffering employed by Linux. You’re also forcing a context switch per interrupt, which is rapidly going to get ugly at 10gig. I’m sure if I stopped to think for more than a couple of minutes, I could think of a large number of extra reasons why this is a bad idea.

        Your use case is pretty much the only acceptable one – prototyping. Writing kernel mode drivers really isn’t that difficult, and the idea it’s prone to buffer attacks is pretty spurious, since Linux (and most other kernels) provide most of the buffer management functions.

        1. No. Please watch either this talk or my talk last year (also linked above).

          Virtually all high-speed packet processing apps use user space drivers nowadays because they are faster. Check out DPDK and/or VPP for examples.

      2. Well, WiFi is rather slow, at least compared to 10GBit Ethernet. So yes, on a modern CPU you should be able to do it in userspace. The question is, how much CPU load does it generate? If you can run a 802.11ac connection at full throughput but it puts 100% load on one core, then that works but I wouldn’t want to use it for more than a proof of concept.

        A hardware driver should consume as few CPU cycles as possible, after all, there is a lot more high level stuff and application code that also would like to use the CPU. More and more programmers seem to forget this little detail.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.