Providing system settings to snap-confine

The snap-confine program reads a number of files written by snapd. To reduce complexity each file is in a different format so that the corresponding parser is easier to write and test. In a perfect world we’d just dump one big file that has everything (say yaml or json) and load it back. In that world we’d have no problem with squeezing a few key=value pairs in a miscellaneous section, to tell snap-confine about things that we currently hard-code as a compile-time choice.

To truly support re-execution on any distribution we need to be able to have the exact same executable of snap-confine work correctly. Currently, from the top of my head, we can, as a compile time choice:

  • control if apparmor is enabled
  • control if seccomp is enabled
  • control where the /snap directory is
  • control if the distribution uses merged /usr or not
  • control which nvidia driver model to use

All of those need to become variables that snapd tells to snap-confine.

I’d like to propose that we add a new file, say /var/lib/snapd/snap-confine.cfg that can contain simple key=value pairs. This file would be written by snapd (or even shipped in a distro pacakge as it is all constant) and read by snap-confine. The file would be easily extensible and unknown values could be ignored by snap-confine. With a few patches we could then replace each compile-time choice to a runtime choice. Eventually, as the number of patches drops to zero and number of compile time choices drops to zero, we could enable re-execution everywhere.

What do you guys think?

We already have something very close to that today at /usr/lib/snapd/info. We can probably just enrich it, being careful about which options we pass over and how, so we avoid turning it into a kitchen sink.

I was thinking about it but I think it ought to be a file in /var/lib/snapd as the contents will depend on the kernel we happen to boot with (apparmor).

And who will write that file when you boot with a different kernel? What happens to the services that started before that?

This is an ongoing problem but I think snapd needs to write that file. Perhaps it could be all done via systemd units so that the right order is preserved. In either case it cannot be a static file.

This is an on going problem which this thread is aiming to solve, so we need to answer it appropriately before we take a solution as good.

My aim is to de-compose the problem. We know that snap-confine has hard-coded behaviour that needs to become dynamic. We know we don’t want to add logic that needs to be kept in sync in snapd and snap-confine. Loading the file is uncontroversial. The remaining issue is what to do at kernel change. We (today) have the same issue that affects all security profiles.

If the dynamic behavior is based on kernel abilities, why are we going to create an external tool which is then added on a boot sequence so it can update a file which is then read by snap-confine so it can then take a decision to use apparmor or not? Alternative: add the exact same logic in snap-confine and read/write nothing?

That’s the sort of thinking we need to put on this problem before we create the kitchen sink. We need to think through the actual problems we’re solving before we do busy work which seems to make progress but in unclear ways.

I think the external tool is the better approach. The thing could be written in go and can just inspect release and uname and write the needed data. Doing this in snap-confine will take more time and will be more fragile. I +1 this approach.

Clearly you +1 your own proposal, but that doesn’t change the points above much I think. :slight_smile:

Well, I meant the part that you suggested. I think the idea that snap-confine read a key=value file is easy to agree on. The devil is in the details (where the file comes from)

Yes, I also mean the part I suggested (!?). I don’t yet see the value of adding that much complexity simply to move the decision making process into an external tool which then needs to put into the boot sequence so it can write down a file so a different tool can read from it and use the earlier decision, when we can simply decide on it at once.

I think the key here is that we need to do this for re-exec and that we don’t want to maintain what snapd knows about in snap-confine as this may lead to inconsistencies. We’d have to add a parser for a similar key-value file to load /etc/os-release so at that stage we can just as well read something that snapd wrote.

And the early boot with new kernel problem doesn’t change at all. We still need to rewrite the security profiles when that happens.

I feel like we’re going in circles. We cannot just read what snapd wrote because that’s too late, and if we have that inside an external tool then that tool may be snap-confine itself. Let’s discuss this in a call please.

It doesn’t have to be snapd. It could be a helper that is written in go and reuses snapd code. It should not be in snap-confine because it cannot reuse the (mostly already written in release.go) code. Lastly some of the code is lookup-table like and we just want one (source).

I’m happy to have a call tomorrow but I think there are very clear parts (snap-confine needs this extra data, we want to use/reuse existing go code to provide this data) and parts that need more discussion (how does kernel change and early boot come into play).