We talked about this a few times and it has come up again here in the rally. Let’s implement this when we have some time.
Applications don't provide manpages
Can snaps install manpages?
Speed-up Snap Building
How to embed man in a strictly confined snap and have it invoked to display a custom man page
The plan of record was to write a (seccomp? apparmor?) profile for man, that would benefit everybody, and then let snaps include mans and copy them to a predefined location that is added to
I think I dropped the ball on this: I was meant to file a debian bug against mandb in debian, and I didn’t.
I probably need to catch up with whoever it was spoke with back then, but I don’t even remember who they were.
When John and I discussed this before his posting here, I recalled some of the details. In the previous discussion, @cjwatson preferred an approach that was both upstreamable and helpful to everyone. As such, the man command would not rely on an apparmor profile or doing something different if a man page existed in a particular path, but instead man would be modified to operate securely with untrusted input (ie, a man page from a snap). This would most likely involve the man command being modified to create a very restrictive seccomp policy when processing any man page. In this manner, the snap somehow declares what man pages to make available, then snapd only has to do the work to put those pages where man expects them. Since man is hardened against untrusted input, any snap is allowed to do this by default.
I posted this comment in bug 1575593:
I’ve uploaded man-db 2.8.1-1 to Debian, and that will shortly be synced into bionic; this uses a combination of strategies involving seccomp and AppArmor to confine the processes that parse manual pages.
How much do we care about backporting some or all of this to earlier series before allowing snaps to make manual pages available? Considerations here:
- The AppArmor support is probably relatively easy to backport. It isn’t upstream as yet, since AppArmor profiles tend to have a lot of hardcoded distribution-specific paths and I haven’t figured out how to sensibly distribute them upstream. It does a reasonable job of protecting some of the most complex pieces, such as /usr/bin/troff, though mainly only in terms of forbidding them from writing to anywhere interesting on the filesystem (they could still open network connections or whatever). It doesn’t generally protect components of man-db itself.
- The seccomp support is upstream (technically as of 2.8.0, but 2.8.1 fixes several serious problems). It uses a pretty restrictive filter for most things, basically just allowing processes to operate on themselves and to do the sorts of things you find in data-transforming pipes, and a slightly more permissive filter that allows limited file creation for the various groff processes that need the ability to create temporary files. It would be very invasive and difficult to try to backport this.
- This is all proactive hardening: I don’t think there’s been an actual reported vulnerability in any of the relevant code for 15 years or more. Of course it’s possible that that might change if it were a way out of snap confinement rather than an interesting curiosity.
Thanks for pushing that forward!
I’m wondering if we should provide something like a snap man command as a stop gap for all releases. This might even be implemented by leveraging a snap installed on first use that runs the tools confined, perhaps? It might also fallback to the system man pages, so that it may be aliased as man itself if the user chooses to.
Maybe. I’m a bit wary of that creating confusion about which command people need to run, and being a “sticky” interface wart that has to hang around for a long time.
Alternative proposal: I could backport just the AppArmor support to older releases. That still provides pretty good coverage, even if imperfect, and I think it’s a reasonable compromise between backporting effort and actual risk given that this is proactive hardening rather than a response to something known to be full of holes.
If there’s a solid reason this definitely isn’t acceptable, then I think backporting the whole thing would be less overall effort than “snap man”. It’d require a new upstream version of libpipeline (API additions), and the man-db patch would be a few thousand lines, so I don’t particularly relish it; but there’d be many fewer moving parts and it wouldn’t expose a changed interface to users.
For Ubuntu, IMO backporting just the AppArmor profile changes would be sufficient to enable the feature in snapd. snapd is of course cross distro and feeding even the apparmor profile to other distributions would be problematic, let alone the larger patch for the seccomp changes. As such, I’m not sure what to suggest… some distros might want to take the man page feature without the man command hardening, some may not. Does it make sense to make the snapd man support (perhaps compile-time) conditional? This way Ubuntu can backport the apparmor changes to 17.10 and earlier, take the full set of changes in 18.04 and other distros can decide what to do for themselves.
The idea of having something builtin is precisely offering a fallback that will work no matter what distribution people have at hand, and whether particular patches for man/etc were applied.
Maybe. But it’s a bit of a rabbit-hole: for instance, it wouldn’t work with
:Man plugin, and probably a whole bunch of other stuff along those lines too; completion would need work (and to be fast); there’s no particularly clear way to integrate it with
apropos (bearing in mind that when you’re searching for an installed man page system-wide you really don’t care how it got onto the system); and so on.
Plus of course people can always do
man -l /snap/man/... anyway, and users who are more familiar with
man than with snaps will probably do that before finding
snap man. So IMO, if there’s actually a credible concern about confinement escapes via
man (taken as a given for this whole thread, I suppose), then there’s no way around hardening
I’m concerned about creeping interface cruft that will end up being spread around in not-particularly-snap-related code that I have to help maintain, and hang around for years after my hardening patches are present everywhere, when maybe a bit more effort now could avoid that. That’s why I’m trying to feel out acceptable parameters more generally, rather than the single possibility of a builtin command.
Personally I think that, as there is a trivial but essential integration step a distribution needs to do for
man to find the snap manpages, and as mandb’s security track record is rather good, and there’s a reasonably easy way of a user looking at a manpage if the integration step has not been taken, there isn’t a need to add anything further to snapd beyond the work needed to expose the manpages in a single location.
Concretely, and as a strawman, snapd can start exposing manpages in
/var/lib/snapd/man/. In Ubuntu and other places that carry the patch (or that consider it unnecessary),
/etc/manpath.config would be updated to search there; in a distro that doesn’t do the integration work, a user can
MANDATORY_MANPATH /var/lib/snapd/man/to their
~/.manpath— this one might be simpler to communicate.
- load the man pages by hand via
For people that are looking for manpages, are using snaps, and are using a distro that hasn’t done the integration work, telling them “drop this
.manpath in your home” seems fine to me.
Remember this extra hardening is upstream, so other distros will get it eventually (although I assume it’s compile-time optional), and mandb’s security record is such that even without it we’re probably ok.
To put it another way: distros that aren’t going to be picking up the hardening work are probably devmode already…
While I’m not sure I agree with the statement that distros not picking up the hardening work are probably devmode (Mint and its derivatives come to mind), I do agree that man has had a reasonable security track record. We should be doing what we can when passing uncontrolled input from snaps to unconfined programs. Sometimes we do that through interfaces (eg, dbus services) and sometimes we harden the system (eg, bash completion). Colin has done great work here (thank you!) and IMO is doing it the right way-- the code went upstream and everyone will eventually benefit.
John’s proposal seems like a nice compromise. With his idea, snapd is not overly complicated with compile time options or extra commands; it just puts the man pages from the snaps somewhere outside of MANPATH. If a distro chooses to integrate sooner via packaging, the distro is free to pickup the man hardening sooner too. If the distro doesn’t, snapd honors that choice by not updating MANPATH itself and a sysadmin can choose to set the manpath globally or a user can choose to do so locally for herself.
In thinking about this more I think it is also worth noting that irrespective of snapd, man is currently processing untrusted user input during tons of package builds (I suspect the man code has been analyzed for vulnerabilities quite a lot over the years as a result) and that’s why exploitable parsing bugs/etc are treated as CVEs with priority by all the distros. snaps extend the reach of those vulnerabilities of course, but John’s proposal honors distro and user choice until everyone can benefit from Colin’s great work.
If there is agreement that the processing of the man pages is secure enough, doing something simpler definitely sounds good. That said, we still need a polished interface that tends to work, probably via snap man, because we want to expose a way that tends to work without people having to guess what a particular user has done to their own environment.
Without that, consider that every single time a third-party has to say “read the man page”, they have to attach instructions… and everytime someone reports “the man page doesn’t work”, they have to ask whether the user has done X, Y or Z2, to make sure that man pages work at all. That’s not how a polished user experience should feel like.
Another alternative is to just go ahead and integrate with the real man so that it indeed just works without special flags.
Is there any update on this feature?
I’m the snap maintainer of two command line tools (tio and lxi-tools) both of which could really use support for man pages.
Is there any action here yet? if I have some manual installed from snap, for example
I can read it by doing:
Can snapd manage that for me?