Snap layouts

One of my snaps that uses layouts suddenly gets rejected on automatic review in the store:

invalid source mount: '$SNAP/api/tmp'(should be a legal path and not start with: /boot, /dev, /home, /lib/firmware, /lib/modules, /lost+found, /media, /proc, /run, /sys, /tmp, /var/lib/snapd, /var/snap lint-snap-v2_layout_target ($SNAP/api/tmp)

full review output

As you can see in the snapcraft.yaml source, I’m mapping $SNAP/some/path to $SNAP_DATA/some/path. The application running in $SNAP/api expects everything to exist beneath its root directory, but some of those have to be writable. The previous snap revisions (last one built on 2019-07-04) went through review just fine. I tried with and without the passthrough wrapper, so I presume that the store gained layout linting in the meantime.

Is this expected? What can I do to have my snap pass review again?

It did. I’ll take a look and respond via the store review process.

Ok, as you probably saw, I approved these. The fix is in master and I’ve requested a store pull.

1 Like

Thank you for the fast response + fix + approvals, much appreciated!

Is there a repo/status page where I can see if the fix has been deployed, so that I don’t push revisions until this passes again?

No, but it just got deployed so feel free to upload again :slight_smile:

1 Like

Given that review-tools are a separate public project, it might make sense for the dashboard to display somewhere which revision it is using ATM, probably not interesting for everybody and not super high-prio, but not silly either.

@roadmr - how feasible is this?

Currently, the version of the review tools a particular snap was scanned with is shown as part of the review results. For example, go to:

under "Automated review " there’s an expandable section with “X passes”, and expanding that will show the tools version such as:

20190717-1931UTC click-reviewers-tools version

But this, of course, requires doing a snap upload to see which tools version is active at the moment.

I’ll look into adding this information in a generic place, though we’d have to find such a place and also decide if it’s OK to show this (i.e. is it sensitive information in any way?).

  • Daniel

As a user, I’d intuitively look over at https://status.snapcraft.io (though the deployed review-tools version is not really a status in that sense) or in the dashboard of my deployed snaps. But I guess the multitude of build options (build.snapcraft.io, launchpad project, …?) makes it hard to find a sensible and central place to put that information.

@zyga-snapd what’s the motivation behind not allowing a symlink to be mounted on top of an existing file? i.e. I want to do this:

layout:
  /usr/bin/gjs:
     symlink: $SNAP/gnome-platform/usr/bin/gjs

with /usr/bin/gjs existing in the base snap as a regular file (it doesn’t actually exist yet but pretend that it does). I am able to do this locally:

$ echo original > gjs
$ echo new > my-gjs
$ ln -s my-gjs new-link
$ sudo mount --bind new-link gjs
$ cat gjs 
new

Is there a reason we can’t do this in snapd? If I remove the original symlink, then the bind mount still shows the original file that the symlink pointed at, so at first glance I don’t think that there’s an issue around the target of the symlink being “swapped out”.

FTR, this is what snapd says when I try to do this:

cannot update snap namespace: cannot create symlink in "/usr/bin/gjs": existing file in the way

There’s no “because” reason. It’s just a limitation of the current implementation.

As a side-effect of investigation into the issue with nested mimics we discussed an idea where Assumptions type could carry information about the base snap and content snaps enough so that we can know that a mimic needs to be created while computing the plan of operation. This would allow us to replace existing filesystem entries with other entries reliably.

Right now we cannot do that because of how the code is laid out:

  • we process entries one by one
  • as we process them we can discover that a place is read-only and we cannot create a directory/file/symlink
    • if that happens we construct a mimic

If we knew about the filesystem via the Assumptions type we could:

  • simulate creation of each element
  • gather and reorder all mimics we would create
  • sort them so that outermost mimic is created first (this avoids nesting)

This would also allow us to see the kind of object present at a given path and create a mimic so that we can replace it (remove / recreate).

1 Like

is there a “best practice” advice of when to use bind-file or bind vs symlink? i.e. when would we prefer to use a symlink over binding and vice versa?

Symlink is generally more light-weight and unlike a bind mount, can be removed by the application when used in locations such as $SNAP_DATA. Applications more commonly identify symlinks-vs-regular-files than they do with bind mounts so you may need to use a bind mount to convince a picky application to use something but in general symbolic links should be preferred simply because they are cheaper.

2 Likes

Hello @zyga-snapd, what i understand is Layout will bind the “$SNAP_DATA/etc/foo.conf” file with the host “/etc/foo.conf” path, maybe you can correct my understanding here.

My question is how i can place foo.conf file in $“SNAP_DATA/etc/foo.conf” path ?

For now, what I am doing is, I wrote a cp command which will copy the foo.conf file from “$SNAP/etc/config.conf” to “$SNAP_DATA/etc/foo.conf” in configure file of hooks dir that will be executed while installing the snap.

Does Layout will do the above task?

You cannot put the file in $SNAP_DATA/anything before the snap gets a chance to execute but on the upside the layout will actually create the file for you. All hooks, even install and configure run after the snap layout has been constructed.

EDIT: so to make it clear, you can just write to the file that was placed there by the layout system.

A post was split to a new topic: Python3 application with external module

12 posts were split to a new topic: Building with snapcraft in docker

It would be nice if it were documented that layouts were not supported in classic containment.

2 Likes

Thanks for bringing this up, and you’re absolutely right. We should have made it completely clear that layouts won’t currently work with classic. I’ve changed the first line to hopefully make it clearer and I’ve added a caveat to the limitations section.

1 Like

Using snapd-glib to configure core watchdog I need to talk to snapd using /run/snapd.socket. When I did that, Snappy debug complains about DENIAL for using /run/snapd.socket and suggested to make use of layouts

= AppArmor =
    Time: Apr 25 14:00:10
    Log: apparmor="DENIED" operation="connect" profile="snap.plt.wtdog.runner" name="/run/snapd.socket" pid=1605 comm="setpet" requested_mask="wr" denied_mask="wr" fsuid=0 ouid=0
    File: /run/snapd.socket (write)
    Suggestions:
    * adjust program to use $SNAP_DATA
    * adjust program to use /run/shm/snap.$SNAP_NAME.*
    * adjust program to use /run/snap.$SNAP_NAME.*
    * adjust snap to use snap layouts (https://forum.snapcraft.io/t/snap-layouts/7207)    

But the post here mentions /run path cannot be used. I tried it anyway using:
layout: /run/snapd.socket: bind-file: $SNAP_DATA/snapdsocket

But, get an error:
layout "/run/snapd.socket" in an off-limits area

So, what is the way out?