2008: MinorFS
About a decade ago, a first proof of concept version of the least authority file system MinorFS saw the light. MinorFS was meant to be used together with AppArmor and the E programming language to provide a least authority stack for building high integrity systems with. Where the Object Capability language E provided application level dynamic least authority constructs and AppArmor provided static least authority at the file-system level, MinorFS was a user space file-system that united these two worlds by providing private file-system storage to pseudo persistent processes, and the ability for those processes to delegate part of their private directory tree to other processes running within the same architectural constraints.
2012: The Rumpelstiltskin Attenuated Tree Graph (RATG) Algorithm
A few years later, thinking about how to make MinorFS more scalable, thinking about if the sqlite database that formed a huge bottleneck to the performance of MinorFS could somehow be phased out, I came up with the Rumplestiltskin Attenuated Tree Graph Algorithm. This simple hashing based algorithm did not just theoretically do away with the need to use a database in MinorFS alike systems, it also created a least authority feature that MinorFS did not allow for: The possibility to delegate read-only attenuated access to shared files. There are currently, to my knowledge, two (unfortunately incompatible) implementations of the RATG algorithm, pyrumpeltree for Python3 and Rumpeltreepp for C++.
The base concept of the RATG algorithm is the use of some kind of server that is seen as part of the TCB. The RATG allows for two least authority operations: decomposition and attenuation. If an object has an access token for a directory, it can use that token to ask the trusted server for an access token for an entry in that directory that it can then delegate to another process. If an object has a read/write access token to a file or a directory, it can use that token to create a read only attenuated access token for that file or directory, so it can delegate attenuated access to another process.
It is important to note that the RATG algorithm flows from a root secret or root token. To create a RATG tree, a root secret is chosen as read write access token for the whole tree. Applying keyed hashing to this token provides us with a hash that shall act both as read only token and as encryption and decryption key for the serialization of our root node. A second keyed hashing operation on this first hash gives us a second hash that is then transformed into a file location for storage of the encrypted serialization of the root node. Once the root node, an empty directory, is serialized to this file, all further operations will need to use a valid access token.
One of the main idioms of capability based security is designation is authorization, and as you will understand, without a valid access token, even designating the root node, or any other node in the graph should prove impossible. It is up to the server to not allow nodes to be created without a valid unatenuated-access token for its parent, and to not allow mutating operations on a node without an unatenuated-access token to that node. Access control on reading operations though isn't in any way needed, given that being able to designate a node is all in itself sufficient information to be allowed to read the data.
If you want to read more on RATG, check out this blog post.
2016: MattockFS
In 2014, when I started doing another M.Sc study in Dublin my time for doing unpaid research and open source development quickly dried up until in 2015 I started my research project for that M.Sc program. As the M.Sc was a computer forensics program, and as I had past experience with the development of the OCFA computer forensics framework, I decided to do my research on Page-cache and access-control concerns in asynchronous message-based forensic frameworks on the Linux platform. In order to complete this research project, I had to write an other user space file-system. One that combined aspects of the CarvFS file system from OCFA with aspects from the MinorFS filesystem. MattockFS, while a proof of concept, implemented a write-once data archive with out of band provenance logging features, and combined this archive with a capability based local message bus geard towards computer forensics applications.
The model of attenuation of access was quite a bit different though from the model the RATG algorithm provided. In the forensic framework context, performance and integrity are the foremost attributes of concern. Confidentiality is nice, but not at the cost of lower throughput. This was especially true within the context of my particular research topic.
If you want to learn more about MattockFS, chech outthese blog posts I made based on a workshop I gave at the DFRW in Überlingen Germany in 2017:
2017: Using the STEEM blockchain for forensic integrity
What if we could add more to the integrity of MattockFS? What if we can use blockchain technology in order to further increase the data and process integrity guarantees MattockFS provides to the forensic process?
So after looking at multiple candidates, the speed and low transaction costs made me end up with STEEM as suitable blockchain. As I described in this blog post, streaming log information into a process that makes a regular (few times an hour) snapshot of the new provenance log entries and hashing information from the framework, puths this information into a Merkle-Tree, stores the Merkle-tree in the MattockFS archive and puts the Merkle-tree root, as a memo field in a micro transaction to @null, leverages the STEEM blockchain integrity properties into MattockFS integrity attribute improvements. And by using @null as target of our micro transactions, it does so in a way that, by burning STEEM, contributes to the platform.
A RATG based MinorFS system: RumpelstiltskinFS ?
Before I started on MattockFS, I was working hard on designing and developing a RATG based version of MinorFS. In 2013 I gave a talk on my progress on what then still went by the name MinorFS at the OHM2013 conference in the Netherlands about the idea of Defeating Trojans with MinorFS2. I later renamed the project to RumpelstiltskinFS, but as with MattockFS my direction had shifted towards forensics and integrity-only, these efforts ended up low on my list of priorities. In the meantime, the technological realities have shifted. Most notably, many of the concepts I worked on for the Trojan defense application of RumpelstiltskinFS assumed a setting where the file-system would work in conjunction with AppArmor or an alternative MAC framework such as SELinux. Facilities that in the current Dockerized reality of today's IT-architectures tend to be hidden under the hood. If I am to truly pick up RumpelstiltskinFS again, hell, even if I continue working on MattockFS, making the system play nice with Docker should be a top priority.
Blue sky vision
My blue sky vision is for MattockFS and RumpelstiltslinFS to become part of one stack that seemlesly connects to both Docker and the STEEM blockchain. Ideally the technology stack , that I shall refer to as The Rumpelstiltskin stack would consist of the following core technologies.
- Docker
- STEEM
- FUSE
- MattockFS
- RumpelstiltskinFS
- SES
I imagine that like the AppArmor/MinorFS/E stack of old, the above stack could allow multiple layers of least authority based privilege seperation for building robust high integrity systems, but I feel that the above stack has time on its side where the MinorFS stack did not. Imagine running containerized capability secure JavaScript subsystems in a Docker container, using a versioning storage system without any actual shared mutable data but with almost all the conveniences of shared mutable data. With a built in capability based message bus that hands over read only access to write-once data existing in a big high integrity archive.
Blue sky vision 1: Docker container tags for actor identification.
Both MattockFS and the old design of RumpelstiltskinFS rely on close dependencies on a MAC framework. Much of the logic for identifying processes in MinorFS depended on AppArmor and info from the /proc filesystem to figure out who the FUSE process was talking to and what delegations should flow from that. There is still a pending feature for MattockFS to enforce restrictions on what process may claim the role of a worker for what named actors.
The first step to make to making the envisioned stack real is adding Docker interoperability and docker image tag based actor identification to MattockFS. The proposed access rules are as follows:
- If an actor runs in a Docker container, a MattockFS config file should specify an actor name to Docker container tag mapping. The actor may only register as worker for a specified actor.
- If the actor runs without a container, no worker registration rules apply.
Blue sky vision 2: Mutable files on top of MattockFS CarvPath using write-once operations.
While MattockFS works with a write-once archive, not everything can be expressed using write-once archive files. In some situations we may want to use mutable files. Could we model these on top of write-once files? Consider that MattockFS uses CarvPath designations to designate the underlying archive data, CarvPath annotations can help with a type of versioned mutability.
Imagine we have a read only carvpath *593920+8388608.crv", Now imagine one 4096 byte block in this file is changed. Rather than writing a whole new file, we could use a carvpath that includes most of the old file and only a small appended new piece of data archive. "593920+8355840_ 1342771200+4096_8953856+28672.crv".
Blue sky vision 3: Running RATG on top of MattockFS
If we combine the above two features and rethink the RATG algorithm a tiny bit, we should be able to almost map a RumpelstiltskinFS implementation on top of MattockFS. For this, I propose extending the MattockFS use of Redis. Currently MattockFS uses Redis for CarvPath annotations that are too long to be mapped to an actual file-system. I won't go into the details, but the base idea is that long CarvPath tokens are replaced by their hash in their file-system representation and the Redis DB is needed for mapping them back to the actual long carvpath.
Because MattockFS already depends on Redis, we can add another key value store to accommodate layering RumpelstiltskinFS on top of MattockFS. We map a string containing an archive ID and a storage hash (Key3) to a JSON structure with acombination of inode like info and a versioning chain. An example:
{
"version": 17,
"latest": "593920+8355840_ 1342771200+4096_8953856+28672.dat"
"size": 8388605,
"type": "f",
"prev": "931729408+170.inode",
"ctime" : 1542987129,
"mtime": 1542987129
}
Now the carvpath designated by "latest" will be AES128 encrypted using CTR mode in order to play nice with our carvpath based mutability.
There are some limitations to this approach to mutability. We need to be rather course when it comes to using file locks for writing. After all, writing means creating a new version of the file as a read only carvpath.
I realize my blue sky vision here can be dificult to wrap your mind around if you are unfamiliar with any of the FUSE filesystems discussed. I hope though that this blog post reveals at least part of my vision for the Rumpelstiltskin technology stack. I hope enough to comunicate the potential for such a stack.
Things are still early drawing board stage, but I really would appreciate feedback on my vision here.