Clicking a hyperlink in a PDF fails to open it if the default browser is a snap

Bug #1794064 reported by Olivier Tilloy
94
This bug affects 18 people
Affects Status Importance Assigned to Milestone
apparmor (Ubuntu)
Confirmed
High
Georgia Garcia
Jammy
Confirmed
High
Unassigned
evince (Debian)
New
Unknown
evince (Ubuntu)
Triaged
High
James Henstridge
Jammy
Confirmed
High
Unassigned

Bug Description

[Impact]

 * Users cannot open a hyperlink in a PDF opened with evince when the default browser is a snap.
 * The fix creates a snap_browsers abstraction on AppArmor which can be used in a transition for when the browser is executed. The snap_browsers abstraction provides the minimal amount of permissions required to execute a browser provided through snaps. This is a workaround since AppArmor currently does not provide mediation/filtering on enhanced environment variables.

[Test Plan]

 * Make sure the default browser is provided through the snap store.
 * Open a PDF that contains a hyperlink using evince and click on the URL.
 * The browser should open the requested URL.

[Where problems could occur]

 * If the browser or snap core update to have new requirements for opening a browser, then the current policy could become obsolete and will need to be updated again.

Revision history for this message
Olivier Tilloy (osomon) wrote :
Revision history for this message
Olivier Tilloy (osomon) wrote :

Note that this works with the evince snap, only the deb package is affected.

Revision history for this message
Olivier Tilloy (osomon) wrote :

I can "fix" the issue if I add the following two lines to /etc/apparmor.d/abstractions/ubuntu-browsers and reload the evince profile:

  /usr/bin/env rmix,
  /usr/bin/snap Cx -> sanitized_helper,

Probably not acceptable as is because this would allow executing any snap, not just chromium. And snaps are not guaranteed to be strictly confined (e.g. classic/devmode).

But a rule on /snap/bin/chromium is not good enough as /snap/bin/chromium is a symlink to /usr/bin/snap.

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

I went through this the other day with a personal profile. We probably can do something along the lines of:

/{,snap/core/[0-9]*/}usr/bin/snap mrCx -> snap_browser,

profile snap_browser {
    #include <abstractions/base>

    /etc/passwd r,
    /etc/group r,
    /etc/nsswitch.conf r,
    /dev/tty rw,

    # noisy
    deny network inet stream,
    deny network inet6 stream,
    deny owner /run/user/[0-9]*/gdm/Xauthority r, # not needed on Ubuntu

    /{,snap/core/[0-9]*/}usr/bin/snap mrix, # re-exec
    /etc/fstab r,
    @{PROC}/sys/net/core/somaxconn r,
    @{PROC}/sys/kernel/seccomp/actions_avail r,
    owner @{PROC}/@{pid}/mountinfo r,
    owner @{HOME}/.snap/auth.json r, # if exists, required
    /run/snapd.socket rw,
    /snap/core/[0-9]*/usr/lib/snapd/info r,
    /snap/core/[0-9]*/usr/lib/snapd/snapd r,
    /var/lib/snapd/system-key r,

    /{,snap/core/*/}usr/lib/snapd/snap-confine Pix,
    /sys/kernel/security/apparmor/features/ r,

    # allow launching official browser snaps. This could be abstracted into an #include or tunable
    /snap/chromium/*/meta/snap.yaml r,
    /snap/firefox/*/meta/snap.yaml r,
    # ...
  }

Revision history for this message
Olivier Tilloy (osomon) wrote :

@Jamie, given your recent work on the evince apparmor profile, should that be assigned to you?

tags: added: snap
Changed in evince (Ubuntu):
importance: Undecided → High
Revision history for this message
Vladimir Kondratyev (vladimirkondratyev) wrote :

After transition to snap the Chromium is not usable for me. I have a lot of PDFs with hyperlinks and they stopped working. Is there any workaround other then migrating to deb Chrome?

Changed in evince (Ubuntu):
status: New → Confirmed
Changed in evince (Ubuntu):
status: Confirmed → Triaged
assignee: nobody → Jamie Strandboge (jdstrand)
Revision history for this message
Olivier Tilloy (osomon) wrote :

This has come up again, now that the default browser in impish is the firefox snap (see https://discourse.ubuntu.com/t/feature-freeze-exception-seeding-the-official-firefox-snap-in-ubuntu-desktop/24210/107).

Jamie, I assume this should be unassigned, as you're not actively working on this, are you?

Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in apparmor (Ubuntu):
status: New → Confirmed
Revision history for this message
Ian Johnson (anonymouse67) wrote :

Also I'm not sure I agree with jdstrand's apparmor profile which includes:

    /run/snapd.socket rw,

which I don't think we want to grant to any PDF file opened with evince?

Changed in evince (Ubuntu):
assignee: Jamie Strandboge (jdstrand) → nobody
Revision history for this message
Jamie Strandboge (jdstrand) wrote :
Download full text (3.6 KiB)

Olivier, yes, I shouldn't be assigned. Ian, you're right the profile is suboptimal (it's also old so likely needs updating).

Do note that this is a separate named profile and evince (and if this is put in an abstraction, anything that uses the abstraction) only has the `/{,snap/core/[0-9]*/}usr/bin/snap mrCx -> snap_browser,` rule which means that it is able to run the 'snap' command (needed since everything in /snap/bin points to /usr/bin/snap) which at the time I wrote the profile meant that access to this socket was needed as part of snap run. IIRC, snapd should be protecting certain actions by uid connecting to it (eg, you are root or not), but it has been a while since I've looked at that. Evince is not a snap though so if snapd does any checks on 'is the client a snap' then those would fail and evince would be able to do whatever a non-root user could do with the 'snap' command via the socket.

For snap run, we can see that the snap_browser profile limits what can be used with 'run' since (at the time I wrote the comment) 'snap run' required being able to look at the meta/snap.yaml of the specific snap. This 'works' (worked?) but is brittle since if snap run changed to lift this requirement (eg, 'snap run' just passed the name of the unresolved symlink to snapd over the socket and let snapd start the snap, perhaps via userd, etc) then this falls apart.

The profile was put up as an example as what could be done at the time without any help from snapd. I never particularly cared for it cause it was brittle and not designed. I'm not sure how to fix this, but here are some thoughts:
* evince is just executing stuff from /snap/bin (probably via the system's xdg-open). Assuming xdg-open, the system's xdg-open (or whatever evince is using to decide and launch the default browser) could itself be fixed in Ubuntu to launch a different command that behaved better. This wouldn't necessarily fix other distros (though this is the evince profile in Debian and Ubuntu, so *technically*, if you got this change (to presumably xdg-open) into them, you could update the evince profile in them accordingly)
* In lieu of that, if the profile still worked as intended, snapd could be hardened to look to check more than if the connecting process is root or a snap; it could also see if it is running under a non-snap profile, then limit access to the socket API accordingly. This has drawbacks and could break people who have written custom profiles similar to what I presented.
* I suppose an alternative approach would be to have symlinks in /snap/bin for things that are registered as browsers (or just the default browser) point to a designed snap command. Eg:

  /snap/bin/firefox -> /usr/bin/snap # keep the existing one too
  /snap/bin/default-browser-is-a-snap -> /usr/bin/snap-browser # name is illustrative, TBD

  Now firefox, chromium, opera, brave, etc snaps registers themselves as being capable of being a default browser with snapd, then snapd registers with the system that /snap/bin/default-browser-is-a-snap is the default browser (so system utilities like xdg-open don't need to change) and /usr/bin/snap-browser is written to be saf...

Read more...

Changed in evince (Ubuntu):
assignee: nobody → Georgia Garcia (georgiag)
Revision history for this message
Georgia Garcia (georgiag) wrote :

I was able to reproduce this issue on focal and bionic but not on impish. I'm still investigating why, since I don't see any changes in policies that might affect this issue, but I could have missed something.

Revision history for this message
Alex Murray (alexmurray) wrote :

Is there any option to do this via portals - ie can evince use https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.OpenURI to open the URI? Would then this allow to avoid going via xdg-open?

Revision history for this message
John Johansen (jjohansen) wrote :

I pulled the evince source and there does not appear to be any direct support for portals, and sandbox support is an untasked item on their roadmap. However it still may be possible via the gnome libs, or via dlopen. Those routes would need to be further investigated.

Changed in evince (Debian):
status: Unknown → New
Jeremy Bicha (jbicha)
tags: added: rls-jj-incoming
Revision history for this message
Valentijn Sessink (valentijn) wrote :

I'm running Jammy, upgraded from Focal, and this bug bites me:
(evince:56279): dbind-WARNING **: 12:05:26.897: Couldn't connect to accessibility bus: Failed to connect to socket /run/user/1000/at-spi/bus: Permission denied

... then /var/log/syslog:
[...] audit: type=1400 audit(1649153341.153:384): apparmor="DENIED" operation="exec" profile="/usr/bin/evince" name="/usr/bin/snap" pid=56653 comm="env" requested_mask="x" denied_mask="x" fsuid=1000 ouid=0

tags: added: desktop-lts-wishlist
Changed in evince (Ubuntu):
assignee: Georgia Garcia (georgiag) → James Henstridge (jamesh)
Revision history for this message
James Henstridge (jamesh) wrote :

> Is there any option to do this via portals - ie can evince use
> org.freedesktop.portal.OpenURI to open the URI? Would then this
> allow to avoid going via xdg-open?

Evince is using g_app_info_launch_default_for_uri(), which can use the portal interface:

https://gitlab.gnome.org/GNOME/evince/-/blob/main/shell/ev-window.c#L6775-6778

However, it only does this as a fallback if no desktop file supports the URI. This is intended to allow a confined app to handle some file types within the sandbox before falling back to portals for everything else.

In the case of Evince running on the host system and seeing all the desktop files in /usr/share/applications and other locations, it likely won't ever call the portal API.

It'd be possible to code in explicit portal API calls, but it isn't something that Evince packaged as a flatpak or snap would need. So it might end up as a distro patch we'd be on the hook to maintain forever.

Revision history for this message
Sebastien Bacher (seb128) wrote :

it sounds like something that we should fix one way or another at least for the LTS, maybe in the futur we will have evince as a snap instead and the situation will be different. Could you suggest a patch for review with the change you described?

Revision history for this message
Georgia Garcia (georgiag) wrote :

I'm working on a SRU for apparmor and evince to introduce the snap_browsers abstraction on apparmor as a workaround for this issue.
It is based on these two merge requests from upstream:
https://gitlab.com/apparmor/apparmor/-/merge_requests/806
https://gitlab.com/apparmor/apparmor/-/merge_requests/877

Revision history for this message
Sebastien Bacher (seb128) wrote :

@Georgia, great, should we assign the apparmor line of the bug to you?

Changed in apparmor (Ubuntu):
importance: Undecided → High
Changed in apparmor (Ubuntu):
assignee: nobody → Georgia Garcia (georgiag)
description: updated
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :
Revision history for this message
Georgia Garcia (georgiag) wrote :

@Sebastien, yes, just did. Thank you!

I also attached the debdiffs for evince and apparmor for bionic, focal, impish and jammy. They were also uploaded into the Security Proposed PPA:
https://launchpad.net/~ubuntu-security-proposed/+archive/ubuntu/ppa/+packages?field.name_filter=apparmor
https://launchpad.net/~ubuntu-security-proposed/+archive/ubuntu/ppa/+packages?field.name_filter=evince

Revision history for this message
Sebastien Bacher (seb128) wrote :

@Georgia, thanks for the work! Is anyone from the security team going to sponsor the apparmor updates for you?

Also in the evince debdiff, you added apparmor to the Build-Depends but is that needed? If the intend is to ensure a recent enough apparmor is available on the sytem then the Depends should be enough?

Also evince didn't depends on apparmor before, it's probably fine to change that but I still want to raise the question. What would be the outcome of installing the new evince with an old apparmor? would the missing rules just be ignored or would they create issues?

tags: removed: rls-jj-incoming
Revision history for this message
Georgia Garcia (georgiag) wrote (last edit ):

@Sebastien, yes, I asked people from the security team to sponsor it but we are still reviewing the snap_browsers abstraction. We are denying access to /run/user/[0-9]*/gdm/Xauthority in the policy but if that was the case, then the browser should not have been able to open, but it does open so we are investigating if there's an issue.

Regarding the evince debdiff, even though it looks like the dependency is on Build-Depends on the debdiff, it is actually under Depends. If we don't set this dependency, then the snap_browsers abstraction might not be available. So if the new evince is installed with an old apparmor, then the evince apparmor policy will fail to load and evince will run unconfined.

Revision history for this message
John Johansen (jjohansen) wrote :

@georgiag we could move the abstraction include to "include if exists" to take care of the depends. Generally speaking evince shouldn't depend on apparmor, but of course make use of it if it is available.

Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in apparmor (Ubuntu Jammy):
status: New → Confirmed
Changed in evince (Ubuntu Jammy):
status: New → Confirmed
Mathew Hodson (mhodson)
Changed in apparmor (Ubuntu Jammy):
importance: Undecided → High
Changed in evince (Ubuntu Jammy):
importance: Undecided → High
Revision history for this message
Georgia Garcia (georgiag) wrote :

I made some changes to the patches I submitted previously. In summary, I added permission to Xauthority files in the AppArmor abstraction and changed the dependency of AppArmor in Evince to "Recommends".
Please let me know if it looks okay or if there's any changes I should do
They are in
https://launchpad.net/~georgiag/+archive/ubuntu/test3/+packages

Revision history for this message
Alex Murray (alexmurray) wrote :

@georgia so the usual process (as per https://wiki.ubuntu.com/StableReleaseUpdates) from here would be to first get the changes into apparmor/evince in the current devel release (kinetic) and once it is verified that they are working fine there, then we backport them to jammy etc.

Revision history for this message
RichardNeill (ubuntu-richardneill) wrote :

Still broken, 17th September 2022 in Ubuntu 22.04.
Evince prints the following message "env: ‘/snap/bin/firefox’: Permission denied"
Workaround: https://github.com/popey/unsnap

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.