Thanks very much for coming, is audio okay, great, thanks.
So we're presenting basically how we can use ComposerVas, which is sort of a new type of
file system in for containers and root files system of metal systems, with UKI to produce
a chain of trust all the way through to the root files system from Secure Boot.
This is just like a figure of expression in English, if you don't know it, it's basically
the idea that if you deliver something to somebody, they should be able to trust that
it wasn't tampered on the way.
So yeah, just like I said, you know, we got Secure Boot, we can verify the kernel,
the init RAM-a-fass, but as soon as you like hit a knit, it can do whatever it wants.
And you can't really trust the system that's based on that.
And this is a goal, this is something that's come up over and over again, people talk about it
a lot, we need to be able to trust the root files system, it needs to be immutable, and
it needs to be verified.
So what is ComposerVas, the say this is point to you, you can like I'll leave now, it doesn't
exist, but it tried to exist, guy named Alex and went on LKML once upon a time, and
LKML is kind of a fun place sometimes.
And he had this great idea and it was just like, yeah, no, sorry, not going to happen.
But here's why it's not going to happen, because if you kind of look at, you know, overlay
a fast kind of sound similar to what you're doing, and with, like, FSVarity and stuff,
we could make something work here.
Yes, FSVarity, for people who don't know, it's basically a way of you can verify the contents
of a file down to a single hash.
And it's supported by regular file systems, more are increasingly supporting it, so
far, like the most common ones already do.
And yeah, unfortunately, it doesn't do directories and stuff.
So basically, you're in a situation where you have a regular file.
You can't trust its metadata, you can't trust the layout of the file system, but if you
have that one regular file and you open it, and you're going to read its contents, you
can at least know what contents you're going to get.
And that works by measuring the file, which is built on a maclotry.
And the reason that sound is for efficiency, when you pull in a single block of the file,
you don't want to have to hash the entire file.
So it basically builds that up, and then has a descriptor that's necessary for technical
reasons to make sure that files are different sized, don't hash to the same thing.
And then you get the MSVarity digest.
You have to enable that profile.
Once you turn it on for a file, you can never turn it off again.
You can basically delete the file, and that's it.
And then once it's enabled, you can basically say directly, hey, tell me what the digest
of this file is.
And you get that, and as long as you have that FD in your hand, you know, the I-NOS
not changing, it's immutable, you will read that content.
So EROFS is probably the least interesting part of all of this.
It's just another read-only file system.
We like it because the maintainers are really nice, and it has the features we need,
and it's specifically a performance for the use cases we care about.
OverlayFS, probably most people here are kind of aware of what that is.
It's, you know, you upper layer lower layer, and then I go in, like, access file A.
It checks an upper layer, do I have A. If not, then it falls through to the lower layer.
And you use this for, like, you know, if you want a base image usually, and you want
to do modifications to it, then you can do an overlayFS.
And the modifications will only go in the top part, and it's basically serving as a diff.
But, you know, there shouldn't situations you could get into with this naive way that
I've described overlayFS.
Like, what if you want to delete a file? How does that work?
I just said, okay, I look for it in the top one, and if it's not there, you go to the bottom.
If it's in the bottom, how can I make a disappear?
So there's a concept of a way, though, you can start a character device there, if it finds
it, it'll say, okay, this file doesn't exist, because you meant that it got deleted.
Renaming large files is a little bit more complicated, because, like, if I have a very
large file A, and I want to rename it to B, hmm.
Okay, do I have to copy that entire file content up to B?
Fortunately, there's something called the redirect attribute that lets you do that.
And you can basically store that on the file B, and it'll point to file A.
And then when you do a writeout, you can basically move A to B.
And similarly, if you just want to change the metadata on a file, like, you know,
their owner or the permissions or something, then you can use the other attribute.
And something really useful about that is then it will tell you what the original content
should be with FSW if you enable a certain feature.
So it's a way of making sure that also that data didn't change.
And that's, like, really the thing that composes us is absolutely built on the ability
to store this FSW ID digest in the upper file system image.
So basically, we created an undis format.
It looks like this.
Objects are basically just normal files that are hashed by their content.
Using the FSW ID digest, we split the first two characters of the hash as a directory
name just to sort of keep the director's a little bit smaller to optimize lookups.
And images, that's an EROFS image.
And that's a sim link.
It's also stored in the object store.
It has FSW ID enabled, which is going to be important later.
So those locks mean basically FSW ID verified.
And that is the hash value.
So when we open that, we can verify with FSW ID that it actually hashes
to A3, whatever.
OK, so let's mount that.
That's what it looks like inside just our example.
And we mount this as the upper layer of part of an overlay if that's layout.
And the lower layer is that object directory.
And now you maybe can kind of see where this is going.
We can use this redirect feature in overlay if that's which is quite handy to say,
OK, bash is actually, we want you to go and get that file.
We pretend that that's what bash was originally called in the lower layer.
But it's basically like we can use that as a pointer to say,
that's where you get your data from.
So this is sort of the core thing that achieves de-duplication in composed of
s, which is a really key issue as well.
And of course, as I mentioned, that FSW ID thing in doing that redirect,
we can add the other extended attribute, which says,
make sure it has that content.
So we've essentially created the situation where the entire content of the file system
is specified by what's in that URL of FSW ID.
Because the layouts there, all of the metadata is there.
And any time we actually go and get the physical blocks from the disk,
we verify them with FSW ID.
So that lock there, and the fact that the image is locked,
means that we have effectively reduced the entire root file system to that hash value
of 33002.
And if any of the content or metadata changed, that hash value would change.
And the really cool part about this is that we can take an entire compose of s,
and we can sort on one root partition,
along with your normal mutable content.
Like if you have your var, let's say whatever.
These are just normal files on normal file system, like X4 or Butterfaster or whatever.
And yeah, you can stick your normal mutable content alongside them.
These files are FSW ID enabled, so you could delete them.
You can mess around with them.
But you can't mutate them when they have FSW ID on them.
And as long as we verify that hash before we do this overlay of FSW ID,
we're pretty sure we're in a safe situation.
So the way that that ends up working,
a pass over to Timothy for this now.
Okay, are we good?
Yeah.
All right, thanks, Jason, for working us through the compose.
How did it structured?
And now we're going to look at how we actually boot a system,
how we take, we go from having a computer-fest image system,
install somewhere on a root partition,
and how we go from that to having a system that we can boot,
and go to verify this image that we're actually booting this one here.
So the first step here is we're going to build a unified kernel image,
a UKI and so for those that don't know.
Ready, UKI is combining a kernel in trial-fest and the kernel
come online into a single binary that we can later sign.
So the main thing here is that we're going to include in the kernel
kernel line, the hash of the compiler-fest image that we are going to be booting.
So in there you have the hash, you know that you're going to be booting
only this one here, and because of it, we know the hash of the compiler-fest,
we know the full content of the root file system.
So now that we have a UKI, we can sign it with SIG for SIG boot,
with KEEZ, we can put it into the ESP,
and then add the classic VITS that you may or may not want,
so SHIB, which is optional, and usually a boot to the layer here,
which is a system-d boot.
And finally, when you boot your system, you go to firmware,
you've downloaded your enrolled your SIG boot keys,
the side of the firmware, it goes through SHIM, system-d boot,
you pick your UKI, and then if everything is verified, yes,
SIG boot, that is quite recent, yes, SIG boot,
and then it keeps on booting.
And so that's how you get the full chain of trust,
is that has you, has the need from FS, looks inside of the kernel command line,
it finds the composite hash hash,
which is the hash of the error-fest image that is stored on the root partition,
and thus you can figure out which version of the system to boot,
and more importantly, which, like, make sure that all of the content
that we're going to be booting is exactly the one that we want.
Everything that all the files are verified,
and that we only booting this one version of the operating system.
So here on SIG here, as I'm saying, we have all of the persistent content,
we stored, we can be stored on the same partition,
so you can be either different beta-fest subvolumes,
or it could even be different, yeah, different, just very directory,
or if, like, once you can still have different partition,
but the cool thing is that you can do seal everything on one place.
So now that's great, we have a full trusted boot chain,
and that we can rely on,
but how do we actually build all of this?
And one option to do that is to, we're working on this,
I'm building it using a container file, so using container native tooling.
You can, as everything here is just files,
you can build this directly as you would build a container.
So you can start with almost any container image,
like a classic container image, that is traditionally focused on applications,
so it doesn't have any kernel, it doesn't have system D,
it doesn't have any of the system tooling that we traditionally have on systems.
And so you start from this image, you have system D,
the kernel, a little bit of computer-fest tooling,
based on an explicit, the things that you usually have.
You compute the root-fest digest of everything
that you have in your image of all the files,
you compute essentially the whole tree,
and you compute the hash of the root-fest image,
and you inject that into the UPS.
You also build the UKR, you take the kernel from the root-fest,
you generate the EID, or you already have it,
and you ingest the deposit hash.
You create the UPR, you sign it for sick boot,
and finally you add it to the container image.
And that's how you can have everything into a single board,
a single object that essentially is collection of files,
but which can then be translated into this composites repository.
So how do we do actually do that last part?
How do we take a container image and make it work at an installed instance
on the root-fest system?
It's a project, so it's a site project,
essentially to the composites project,
which is written in Rust,
and does all of this plumbing,
and making sure that you can compute the root-fest digest
from the container image,
and can mount these files systems
when you actually booting it up.
So it has support for cooperating,
so only your container image is,
just what we did building a noise through a classic container build process,
and completing that into actual root-fest system,
and irrefest images, and that are a focal pose of this.
We end all of the thing around asynchronous explanations,
so if you use container images in the past,
you know that essentially there's no asynchronous inside of a container,
usually it's hidden,
and so all of the asynchronous levels and everything,
they are not really taken into account generally.
So this project makes sure that the listening labels are correct,
and everything.
So this works based on a good book for any other tools
that use special extended attributes,
that are not really handled by containers right now.
And it manages all of the boot resources
unlaying using the boot loader specification.
So right now, if you have your AI, you can directly drop them
in the right places.
And it does also the updates,
and make sure that you can actually install updates.
And so we can see this is working progress in a sense.
We welcome contribution, of course.
We'll see later where we want to take all of this.
All right, so let's do a little demo of what this looks like
on a final system, so.
Okay, let's work.
All right.
So here we're building a system that has been built
with all of this tuning.
So it was system DBT showing a first.
All right, I'm learning as root.
How it's variable enough?
No, that did not help.
Sorry, are we good?
Okay, so we've got to build a name old
and we loaded our own key.
So we don't even need anything like here.
We can't reset everything.
So we loaded our own secret boot keys.
And we put a boot CTL, you know that we're building a
UKI and it's system DBT loading up our system.
All right, so we're then going to take a look
at actually what this looks like like on the disk.
So if we take a look at slash boot, we have,
here essentially, it's like it's a fake.
In a sense, it's the ESP.
So we have the UFI directory, all the UKI, etc.
And in the end, we only have two partition.
We have the ESP and the root disk,
multi-sciss route, where we have all the composites stuff.
So if we look at the slash boot point,
it's another layman's point because it's composites.
It's a composition of different things.
If you look at the kernel common line,
you have the composites hash.
And if we go into c-stoot,
she's kind of like the rule, rule, the rule,
the partition.
You have the composites directory.
Inside, you have both the objects,
which are like all the files and the image,
which is the interface image that is used by composites.
So if you measure the FSVD hash of this file,
it's the one it's stored under.
So like we know that it's the right one.
And if you look at the objects on the system,
then you have essentially all the files of your root partition
that are stored there,
hashed under the FSVD digest.
Then if we take a look at the error-facimage,
the composites image,
and we take a look at the specific file inside of it.
So here, pick the time zone for bristle.
And we can find out like it's the first video.
FSVD hash under which it's stored.
So if I reboot the file from the object store,
I replace it with the focus content.
And then I take a look at it.
Then I do get the file, which is okay.
No problem here.
But if I take a look at it's rule,
like where it's actually mounted on the root file system,
then the kernel will tell me,
no, that's not going to happen.
First of all, I just bought the file.
There's no FSVD digest on it.
So it refuses to open the file.
And then even if I enable FSVD,
then it obviously has a different FSVD hash,
and one, it should be having as part of the image.
And so the kernel is still refusing me from opening it.
All right.
So where do we go from here?
So we have a few plans.
If you remember, if you've seen or put a demo presentation
at all systems go, essentially it was vision zero.
This is like the evolution of this.
When we said at the time that the future plans were there,
well, we've made the future plans,
and now we have further future plans.
And the idea here is we,
the computer first project needs self.
It's mostly distribution access nature.
You can pick almost a distribution.
Right now we have integration forward,
drag it and you need audio,
but you could make it for other tools.
And we want to integrate that with BTC,
which also has kind of a goal of being
as much as possible distribution agnostic.
And the BTC project,
it's the bootball container project,
we're trying to make those images
where we take a container,
and make it the transport format,
do format for building images for systems
and distributing them to systems.
Ideally, we would move also,
that to that kind of format for other methods,
all the system that are used is always read right now.
So we have the flat packs,
and that are heavy users of always read.
That could potentially use composite files as well.
And ideally, we also could use it for container images.
So if you imagine a system where you would have both
the container images and the system,
the root partition inside of the same composite first tool,
you would get very interesting properties
around dedification and memory users.
So like if you had, for example, the GDPC,
that would be coming from a container or from the system,
you would have the same file stored in the composite first repository.
And as the same file is the same,
I know it would be the same file in memory,
in the cache, in the kernel cache.
So if you had multiple containers coming from different places,
different base images,
but still using the same GDPC would still get one copy in memory.
So it's really interesting,
in terms of usage, memory, and disc usage.
Finally, the composite first and GDPC project
have been accepted as sandbox project in the cloud
net impeding foundation.
And so we happy that we can move forward with that.
Here are the link to the repose.
If you want to check this project out,
and we're happy to take questions.
Thank you very much.
Thank you.
The question was if you can go directly from a tar file
instead of from an OCI image.
And yes, I think you can.
I haven't tested that in a long time,
but I think that was one of the first things
that I implemented as a way of getting to OCI images.
I think there's a comment for that.
Yeah, I'm really happy you got that question,
because we had a slide about that, and we took it out for a time.
Yeah, so the key thing here is,
yeah, so basically the question is,
instead of having like the partitioning base,
the invariant layout, what do we bring to the table here?
And yeah, the benefit here, I think,
is that because you have this one file system,
like with these sort of partitioning base layouts,
you have your A partition,
and then the Verity partition for that, your B partition,
and then you have your multiple state partitions.
You have to make a lot of decisions and advance about that, right?
Like you have to say, okay, this is how big I ever believe any image I produce
will ever be, and hopefully you never go over that, right?
Because it's really difficult to change the size of that partition
without doing a complete system reset.
And for example, if you ever wanted to do more than one rollback,
then you would be in a situation where you can't pin anything
except one version.
So I think that those sort of sticking points,
and then another big use case we have,
especially is that we want people to be able to do,
just like with RPMOS,
you can overlay extra packages if you want the mind your system.
That's going to be a big use case for that,
and that really feeds into the,
we have no idea how big this partition's going to get.
So having a single partitioning layout,
where you can sort of dynamically have as many images you want,
and they can be as big,
and also deduplicated on the disk.
I think that's a substantial advantage,
especially for the situations we plan to use this for.
I think that's a good question.
Do you have the integrity of this stack up position?
Oh, look, more of the slides that we take over time.
These are very good questions.
The question was, should we use like DM Crypt in DM Integrity
for this one big partition we have?
And yeah, okay.
So there's this sort of famous problem in the kernel.
You know, the file systems they were written in like, you know, simpler times.
And we didn't expect that they would have to be robust against evil
maids or evil disk firmware or whatever.
And you get file system, maintainer,
selling is all the time.
Look, you can't like expose a file system to entrusted content
because you could basically like tune the kernel.
And yeah, this is kind of an issue with our approach
because if you just have a file system,
and you don't verify that,
and then you let the file system code out it,
maybe there's some problems in there.
So one way of working around that
would be using DM Crypt in DM Integrity.
Yeah, we have different ideas for how that could also go.
Yeah, do you just do that on this one?
Essentially, the idea is that, yes, it is weaker,
but in most cases, you're going to have to open a state partition
somewhere.
So unless your system is fully stateless,
or it doesn't use partition on disk,
then you're going to have to open a looks-incredited partition at some point.
And if you've got a vulnerability that is capable,
or an attacker that is going to inject code into a looks-incredited partition,
it's going to get it anyway.
So the main downside of this is that we cannot just wipe
one partition to refactor or to do a factory reset on a system.
So you can attress that if you think a system has been compromised,
you can attress mostly anything on it.
You have to fully re-install it.
Let's see if you have a slide for this one.
So your security module, he's on the current command line,
hash being the point of trust, where you stop the trust.
What component uses that hash?
Is that the kernel, or is that the user space box?
So basically inside the init RAMFS,
we have a pivot, composed of S pivot, something I forget exactly what it's called.
And it's responsible for the question is what part is the kernel command line
to get the compose of S hash and enforces that?
And that's part of the init RAMFS, so that's also signed.
And it reads the proc command line, it loads that up,
it looks in the root file system, it opens that file,
measures the FSVity of that file.
It confirms that it's exactly equal to what was in the kernel command line
and only then does it proceed.
So if I'm running out runtime and I have the same privilege
in the food OS, and I over mount your whatever process
when you have what happens then.
Yeah, then you can do that.
Yeah, if you want to mount something on top of the root file system,
then yes, you can do that.
You can't, because the signature is the effect of the kernel all the time.
Not just in EW.
Yeah, but yeah.
There's still a lot of things you can do in that scenario
to make things look different and you would think that they are.
If you know a time store, good thing to see you.