It’s been a while since the last Status Update on November 2020 so I thought it would be good to have a catch-up post. Be prepared, this is going to be a long one. After all, I haven’t done one of these in 120 days.
There has been one small change to my development environment. I’ve gotten a CLion license. I’m planning to play around with it for a while to see if it improves my C++ workflow.
DSP / Radio
There has been some good progress on signal processing and radio-related projects since the last status update.
Frequency-hopping spread spectrum (FHSS)
I made a modulator for a frequency-hopping signal, and wrote receiver plugins for SDR Sharp and GQRX. The modulator changes the frequency of transmission based on the hash of the current time, and hops frequencies 10 times a second. It is able to be received and demodulated without problems.
It is possible to share the same frequencies between multiple transmitters, as their collisions are not very common. This modulation is good at avoiding narrowband noise, but it provides no processing gain to the signal as there is no correlation done. All I’ve done is transmit a narrowband FM signal with a hopping frequency.
APT image encoder fixes
There has been some improvements to my APT image modulator apt-encoder. Previously, the images created by GIMP needed to be manually edited to get rid of comments. Now the program knows how to ignore comments in image files.
I wrote a modulator that can transmit image files using the HackRF One. It can draw simple pictures on the spectrogram. The height and width of the transmitted image, which translate to the transmission speed and the bandwidth, can be configured.
I have written an article about it here.
I started learning how to do signal correlation in order to get processing gain from spread-spectrum signals. I haven’t written a full modulator/demodulator yet, but I have tested locally with Python and things are looking promising.
Kernel / OSDev
There has been some kernel development in February. Below are the main points. As always, the kernel source code can be found in gkbrk/kernel.
From the first days of multi-processing in the kernel, it was not possible to pass any data when spawning threads. You could pass a function pointer and communicate with the thread using shared memory. Thanks to some changes in the Task class, it is now possible to push and pop arbitrary objects to the stack of the process.
The first thing I did after implementing this is to make the music player fork to another process so it can play in the background while you are dropped back in the command prompt.
Improved PS/2 driver
One of the first drivers we implemented was a polling keyboard reader. We now replaced this with a proper PS/2 driver that handles keyboard and mouse events. Yes, we also support PS/2 mouse now.
A driver for the “mouse integration” that is common in VM emulation software was also implemented, so we can seamlessly use the mouse in the kernel now.
RNG and entropy pool
The only method of generating random numbers in the kernel was a simple LCG PRNG. This made the random number quality bad, and (most importantly) not suitable for anything that needs to be secure.
We now have a system that can collect and extract entropy from kernel events and CPU interrupts. This means anything that depends on external input, such as keyboard and mouse events, and hard drive access patterns, now contribute to a “system entropy pool”.
For now, the only output is the occasional line on the debug console with a random byte. In the future, I am planning to add a sponge function that will collect entropy and produce arbitrary amounts of randomness.
We were using Ninja as the build system for some time, but recently I switched the
./configure script to emit Makefile syntax again. This was mostly done to integrate better with tooling and to get rid of a build dependency.
We also hash the output file names and put them all in a flat
build directory. This makes it easier to clean the project, and allows us to reuse file names without having a nested build folder.
When using the
./mach command to build, all the subcommands still work the same so there are no changes.
Android application template
I wrote a small utility called bencode2json to convert bencoded data to JSON. This is useful to me because I end up using bencode a lot when prototyping network protocols, but I don’t feel like rewriting jq for bencode.
Since I wanted to use this utility for external data from the network, I wanted to make sure it wouldn’t be able to do anything bad to my system. To this end, I learned about how to use seccomp to sandbox a Linux process. For better security and for a small challenge, I used the strict mode which only lets the process call read, write, exit and sigreturn. This pretty much eliminates almost all attack vectors.
LZ77 Compression / Decompression utility
In order to understand compression algorithms better, I decided to write a worse version of a common compression algorithm called LZ77.
The version I wrote keeps a 255-byte window in order to use only a single byte for the length values. Due to the very small window size, it is only able to achieve a 90% compression ratio on plaintext.
I am planning to play around with different algorithms and larger window sizes in the future.
Container runtime script
In order have more reproducible build without messing around with build environments and configurations, I wrote a shell script that uses systemd-nspawn to start and interact with temporary Linux containers. I decided to call this script runcontainer.sh, you can find it on my github.