Apparmor denials after transitioning to core22 (strict confinement)

One of the parts, asciidoctor, worked as expected with core20:

base: core20
confinement: strict
parts:
  asciidoctor:
    plugin: nil
    stage-packages:
      - asciidoctor
    override-build: |
      set -ex
      snapcraftctl build
      sed -i '1s|#!/usr/bin/ruby|#!/usr/bin/env ruby|' $SNAPCRAFT_PART_INSTALL/usr/bin/asciidoctor

We made the necessary changes to transition to core22:

base: core22
confinement: strict
parts:
  asciidoctor:
    plugin: nil
    stage-packages:
      - asciidoctor
    override-build: |
      set -ex
      craftctl default
      sed -i '1s|#!/usr/bin/ruby|#!/usr/bin/env ruby|' $CRAFT_PART_INSTALL/usr/bin/asciidoctor

And asciidoctor hangs when called due to Apparmor denials:

= AppArmor =
Time: Jun 15 21:06:59
Log: apparmor="DENIED" operation="file_lock" class="file" profile="snap.hugo.hugo" name="/snap/hugo/16159/usr/lib/ruby/gems/3.0.0/specifications/default/abbrev-0.1.0.gemspec" pid=242482 comm="ruby" requested_mask="w" denied_mask="w" fsuid=1000 ouid=0
File: /snap/hugo/16159/usr/lib/ruby/gems/3.0.0/specifications/default/abbrev-0.1.0.gemspec (write)
Suggestion:
* adjust program to not write to $SNAP

etc.

Any suggestions? At the moment I’m inclined to revert to core20, but at some point we’ll need to make the change.

https://github.com/gohugoio/hugo/blob/master/snap/snapcraft.yaml

Well, why does it all of a sudden want to write that lock file? It isn’t like $SNAP has been writable with core20… something in your app behaves different in core22

@ogra Thanks for taking a look at this.

You are correct. The part (Asciidoctor) that we are adding to our app (Hugo) behaves differently under core22. We have no control over the Asciidoctor pacakge.

Asciidoctor is a Ruby gem. When you install the Asciidoctor package, it installs Ruby as a dependency. With core20, the dependency is satisfied with Ruby 2.7.0. With core22, the dependency is satisfied with Ruby 3.0.0.

Again, we can’t control the Asciidoctor package, so I’m looking for suggestions:

  • Is there an interface that we can add?
  • Do we need to move to classic confinement?
  • Is there an idiomatic way to install a Ruby gem in core22 (the ruby plugin was last available in core18)?

i guess no interface could help with this since the problem is with ruby pointing to $SNAP ("/snap/hugo/16159/…") which is a readonly filesystem (squashfs) image.

i’m not a ruby programmer or expert but i would assume it might have a way to tell it where/how to install the gems … if you could make it use some writable space like $SNAP_COMMON or $SNAP_DATA instead of $SNAP, that should work …

I reached the same conclusion, but have been unable to craft something that works. I can find a few examples of snapcraft+ruby+gem for core18 via the ruby plugin, but none with core20 or later.

Thanks again for the review. Much appreciated.

FWIW I just hit the same issue for the vale snap - I was able to fix it by locally patching rubygems to avoid trying to call flock() (and this is based on a fix from upstream) - https://github.com/rubygems/rubygems/pull/5278/commits/27b682c81226838b1254ac5843a3f5b1cb20f076

See https://github.com/alexmurray/vale-snap/blob/e4ea1bd6ec11079c76031e6ff4d7b2674bc6302e/snapcraft.yaml#L67 for actual fix.

@alexmurray Thank you for sharing this! I’ll take another run at the core22 transition for the hugo snap.

This worked great. Thanks again!

https://github.com/gohugoio/hugo/blob/d24ffdde5b34cb848d04db7099f9bf8903099209/snap/snapcraft.yaml

You’re welcome @jmooring - thanks for the original work to get confined asciidoctor and rst2html working in hugo which I shamefully stole for vale :grin:

Passing this along to @anthonyfok.