Desktop: allow access to host system fonts

This issue one of the desktop team priorities, so I thought I’d start a discussion with the aim of getting the necessary changes merged to snapd.

Rationale

The basic problem is that at the moment strict confined snaps need to ship their own fonts. This is a problem for a number of reasons:

  • The bundled font(s) may not cover the end user’s native language.
  • If the snap bundles many fonts, it will significantly increase the size of the snap. For example, the Noto font family covering CJK languages is 285 MB on disk.
  • If the user has selected a different interface font, then there is no guarantee that the snap includes it.

So there are good arguments to allow a snap to use fonts from outside sources. Since font formats are relatively stable (unlike themes), giving a snap access to the fonts on the host system seems like a reasonable path to take. It will also ensure that a font capable of displaying the user’s native language is available.

Requirements

The standard system for managing fonts on Linux systems is fontconfig, so the end goal is to make the fonts available via that system. This is going to involve access to the following data:

  • Read-only access to Font files, which might be stored in:
    • /usr/share/fonts
    • /usr/local/share/fonts
    • ~/.local/share/fonts
    • ~/.fonts
  • Read-only access to fontconfig cache files stored in:
    • /var/cache/fontconfig
    • ~/.cache/fontconfig (this one can probably be skipped)
  • Read-only access to configuration files, which are stored in:
    • /etc/fonts
    • ~/.config/fontconfig
    • ~/.fonts.conf

As pretty much every graphical application is going to display text, I think it would make sense to make the font access rules part of the new desktop interface.

Fontconfig caches

While fontconfig can regenerate its caches in the user cache directory, this will slow down application start up on first run (or any time fonts are changed on disk). Making the existing cache files available is desirable. The caches contain only information derived from the font files, so it shouldn’t represent an information leak.

One issue is that cache files reference the full path name of the directory they cover. This means that if the fonts are bind mounted to a different location, the cache will be invalid. There is some work to solve this upstream (fontconfig bug 101889, but perhaps we can use the layouts feature to help? Or maybe just make sure the core snap contains empty directories at the right locations to use as bind mount points.

Fontconfig configuration files

There are a number of things fontconfig’s configuration files may be used for:

  • Users remapping what the abstract sans, serif, and monospace font names map to
  • System wide configuration for fonts, either restricting a font to a particular language or marking it as a substitute for some other font it is metric compatible with.

Without access to this configuration data, confined applications may pick different fonts compared to those outside the sandbox.

2 Likes

In terms of security, the read-only access to the files you mentioned is fine and is in fact already allowed (except ~/.local/share/fonts, but that is by omission) in unity7, unity8 and x11.

Should we just bind mount say, /usr/share/fonts into the snap’s /usr/share/fonts? Should we use a config file for fontconfig to allow it to see the host’s directory instead (via /var/lib/snapd/hostfs/usr/share/fonts)?

If we show the fonts at a different file system location, then the caches would be invalid. For instance:

$ strings /var/cache/fontconfig/9b89f8e3dae116d678bbf48e5f21f69b-le64.cache-6 | grep usr
/usr/share/fonts/opentype/noto
/usr/share/fonts/opentype/noto/NotoSansCJK-Black.ttc
/usr/share/fonts/opentype/noto/NotoSansCJK-Black.ttc
...

The cache files are memory mapped and accessed directly as data structures, which is why having the full path names to the fonts probably made sense.

The bug report I mentioned in my first post was about adding support for making the caches relocatable, but that work hasn’t been merged yet, and if we can avoid the issue all together by presenting the system fonts under the same paths we avoid the problem all together.

Is this the sort of thing that your layouts work could help with, or would it be better off trying to get empty directories added to the core snap as mount points?

Layouts could eventually solve this but having empty mount points would allow us to solve this x10 faster. As long as we don’t face stacking/layering issues (e.g. desire to merge two directories under one location) it should work OK.

Okay. I made the following PR to help get the ball rolling:

https://github.com/snapcore/core/pull/55

1 Like

I’ve put together a PR to expose fonts to apps using the deskltop interface:

https://github.com/snapcore/snapd/pull/3889

I think it is appropriate to add this to desktop rather than a separate interface, since desktop apps generally need access to fonts, and this shouldn’t open up new avenues for cross-snap communication (it’s just read only bind mounts).

I’m not sure whether it is worth adding this to the legacy unity7 interface too: on the one hand, it would improve a lot of snaps right away. On the other hand, they currently don’t expect to see host system fonts, so this could be a reason for them to migrate.

4 Likes

@mvo has merged my branch, so in a future version of snapd (probably 2.29?), host system fonts should be available to snaps using the new desktop interface.

5 Likes

snapd 2.29 has been released, time to remove fonts from snaps!

7 Likes

FYI, if you’re using also desktop-gtk3 as launcher, you need to use composition to remove them.

See: