The original design goals combined with the analysis of requirements suggest that the best way to build our file system is to have a file-system with no meta-data. This is possible since we can encode the meta-data into the URLs and since our files are contiguous.
When files are guaranteed to be contiguous, all that is required to read a file is a device (or volume), an offset into that volume, and the length of what is to be read. In Haystack's case, this is accomplished with an OID that is a reference into an index which contains the offset and length of the file (indexes are matched to each volume, which is also specified in the URL). We propose to eliminate this index entirely, and encode the volume, offset, and length directly into the URL.
With Haystack, we have a mapping of the form:
volume=264,uid=122608936,pid=35954776,n=3971 -> volume=264,offset=oooooooo,length=llllllllll
In our design, we only have the URL:
volume=264,offset=oooooooo,length=llllllllll
With this design, we have lost the ability to detect invalid URLs (previously detected by comparing the nonce), and we have no ability to mark a file as deleted (previously noticed by removing the mapping from the index file). Additionally, we have allowed an adversary to read our entire volume by requesting a read from offset zero to the length of the volume.
See Threat Model.
We could solve these problems immediately by encoding a header at the front of each user file containing a bit pattern marking the start of the file, a nonce to prevent random guesses, and a length to prevent over-reading. An additional flag (or reserved values) could indicate if a file has been deleted. The problem with this approach is that an adversary can upload arbitrary data onto our volume, so they could fake the start of a file header. An attacker could craft a custom file containing a forged file header, then request a read starting at that forged header. They would then be free to read the rest of the volume based on their forged "length" field.
We cannot maintain a list of valid headers since our goal is to minimize reads and meta-data. One option is to attach a cryptographically secure Massage Authentication Code (MAC) to the file header, but this feels heavy-handed since it is adding more meta-data to the disk, and one of our design goals was to minimize meta-data.
Instead, we observe that we have already shifted the volume, offset, and length meta-data into the URL, so we propose to encode the MAC into the URL as well. We are left with an URL containing:
volume=264,offset=oooooooo,length=llllllllll,mac=mmmmmmmmmmmmmmmmmm
A cryptographically secure MAC will authenticate the message contained in the volume, offset, and length fields. Any changes to these fields will be detected by the system when it verifies the MAC, and the request can be rejected.
Deleted files are still indicated by a header for each file on the disk. This is necessary since the URLs now act as capabilities. The "deleted" flag in the header serves as a way to revoke a given capability.
We are not concerned about reclaiming the space of the deleted file since deletions are so rare in our operating environment / usage model. It would be possible to fill deleted file entries on the disk with smaller files as long as care was taken to leave the old file header in place to prevent the old URL (capability) from reading the new file.
To maintain extensibility of our file system, we also encode a small header onto the volume. This header contains details such as the file system version number, the location of the next byte of free space on the volume, the size of the volume, and the type of MAC used and its parameters (ie, the secret key).
NIBFS := volHead , file*
volHead := identifier, volumeDat, mac
identifier:= "NIBFS" , |version|
volumeDat := |next free| , |size|
mac := |mac family| , |mac algorithm| , |mac parameters|
file := fileHeader, |data|
fileHead := |deletedFlag|
We do not encode version numbers into file headers since it is assumed that all files on a volume will be written with the same encoding scheme.