man -l local-file fails with Access Denied

Bug #1773223 reported by Frank Denissen
12
This bug affects 2 people
Affects Status Importance Assigned to Milestone
man-db (Ubuntu)
Triaged
High
Unassigned

Bug Description

I use dh_installman to install man pages in a debian package. This fails on bionic, but succeeds in artful.

In bionic (version man-db 2.8.3-2)

dh_installman --verbose
        install -p -m0644 ./debian/fden_clean_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_clean_nzb.1
        install -p -m0644 ./debian/fden_create_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_create_nzb.1
        install -p -m0644 ./debian/fden_delete_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_delete_nzb.1
        install -p -m0644 ./debian/fden_grab_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_grab_nzb.1
        install -p -m0644 ./debian/fden_start_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1
        man -l --recode UTF-8 ./debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1 > debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1.dh-new
man: can't open ./debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1: Toegang geweigerd
dh_installman: man -l --recode UTF-8 ./debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1 > debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1.dh-new returned exit code 2
dh_installman: Aborting due to earlier error

man -l <relative filename> always fails, also when executed manually. I can "cat" the indicated manfile without any problem. I also executed the man -l command in strace and found this:
19540 lstat("/usr/local/share/man", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
19540 stat("./debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1", 0x7fff5d390630) = -1 EACCES (Permission denied)

The same command with --debug option:
man -l --recode UTF-8 --debug ./debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1
ruid=1000, euid=1000
rgid=1000, egid=1000
++priv_drop_count = 1
From the config file /etc/manpath.config:

Mandatory mandir `/usr/man'.
Mandatory mandir `/usr/share/man'.
Mandatory mandir `/usr/local/share/man'.
Path `/bin' mapped to mandir `/usr/share/man'.
Path `/usr/bin' mapped to mandir `/usr/share/man'.
Path `/sbin' mapped to mandir `/usr/share/man'.
Path `/usr/sbin' mapped to mandir `/usr/share/man'.
Path `/usr/local/bin' mapped to mandir `/usr/local/man'.
Path `/usr/local/bin' mapped to mandir `/usr/local/share/man'.
Path `/usr/local/sbin' mapped to mandir `/usr/local/man'.
Path `/usr/local/sbin' mapped to mandir `/usr/local/share/man'.
Path `/usr/X11R6/bin' mapped to mandir `/usr/X11R6/man'.
Path `/usr/bin/X11' mapped to mandir `/usr/X11R6/man'.
Path `/usr/games' mapped to mandir `/usr/share/man'.
Path `/opt/bin' mapped to mandir `/opt/man'.
Path `/opt/sbin' mapped to mandir `/opt/man'.
Global mandir `/usr/man', catdir `/var/cache/man/fsstnd'.
Global mandir `/usr/share/man', catdir `/var/cache/man'.
Global mandir `/usr/local/man', catdir `/var/cache/man/oldlocal'.
Global mandir `/usr/local/share/man', catdir `/var/cache/man/local'.
Global mandir `/usr/X11R6/man', catdir `/var/cache/man/X11R6'.
Global mandir `/opt/man', catdir `/var/cache/man/opt'.
Added section `1'.
Added section `n'.
Added section `l'.
Added section `8'.
Added section `3'.
Added section `2'.
Added section `3posix'.
Added section `3pm'.
Added section `3perl'.
Added section `3am'.
Added section `5'.
Added section `4'.
Added section `9'.
Added section `6'.
Added section `7'.
`/usr/man' `' `1'
`/usr/share/man' `' `1'
`/usr/local/share/man' `' `1'
`/bin' `/usr/share/man' `0'
`/usr/bin' `/usr/share/man' `0'
`/sbin' `/usr/share/man' `0'
`/usr/sbin' `/usr/share/man' `0'
`/usr/local/bin' `/usr/local/man' `0'
`/usr/local/bin' `/usr/local/share/man' `0'
`/usr/local/sbin' `/usr/local/man' `0'
`/usr/local/sbin' `/usr/local/share/man' `0'
`/usr/X11R6/bin' `/usr/X11R6/man' `0'
`/usr/bin/X11' `/usr/X11R6/man' `0'
`/usr/games' `/usr/share/man' `0'
`/opt/bin' `/opt/man' `0'
`/opt/sbin' `/opt/man' `0'
`/usr/man' `/var/cache/man/fsstnd' `-1'
`/usr/share/man' `/var/cache/man' `-1'
`/usr/local/man' `/var/cache/man/oldlocal' `-1'
`/usr/local/share/man' `/var/cache/man/local' `-1'
`/usr/X11R6/man' `/var/cache/man/X11R6' `-1'
`/opt/man' `/var/cache/man/opt' `-1'
`1' `' `-5'
`n' `' `-5'
`l' `' `-5'
`8' `' `-5'
`3' `' `-5'
`2' `' `-5'
`3posix' `' `-5'
`3pm' `' `-5'
`3perl' `' `-5'
`3am' `' `-5'
`5' `' `-5'
`4' `' `-5'
`9' `' `-5'
`6' `' `-5'
`7' `' `-5'
is a tty
real user = 1000; effective user = 1000

using pager as pager

path directory /usr/local/sbin is in the config file
adding /usr/local/man to manpath
adding /usr/local/share/man to manpath

path directory /usr/local/bin is in the config file
/usr/local/man is already in the manpath
/usr/local/share/man is already in the manpath

path directory /usr/sbin is in the config file
adding /usr/share/man to manpath

path directory /usr/bin is in the config file
/usr/share/man is already in the manpath

path directory /sbin is in the config file
/usr/share/man is already in the manpath

path directory /bin is in the config file
/usr/share/man is already in the manpath

path directory /usr/games is in the config file
/usr/share/man is already in the manpath

path directory /usr/local/games is not in the config file
but does have a ../man, man, ../share/man, or share/man subdirectory
/usr/local/man is already in the manpath

path directory /snap/bin is not in the config file
and doesn't have ../man, man, ../share/man, or share/man subdirectories

adding mandatory man directories

waarschuwing: /usr/man: Bestand of map bestaat niet
/usr/share/man is already in the manpath
/usr/local/share/man is already in the manpath
add_nls_manpaths(): processing /usr/local/man:/usr/local/share/man:/usr/share/man
checking for locale nl_BE.UTF-8
manpath search path (with duplicates) = /usr/share/man/nl:/usr/local/man:/usr/local/share/man:/usr/share/man
adding /usr/share/man/nl to manpathlist
adding /usr/local/man to manpathlist
adding /usr/local/share/man to manpathlist
adding /usr/share/man to manpathlist
Removing duplicate manpath entry /usr/local/share/man (2) -> /usr/local/man (1)
final search path = /usr/share/man/nl:/usr/local/man:/usr/share/man
++priv_drop_count = 2
man: ./debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1: Toegang geweigerd
frank@panter:/mnt/packet/linux/bionic/source/fden-usenet/fden-usenet-3.2$

In artful (version man-db 2.7.6.1-2):
dh_installman --verbose
        install -p -m0644 ./debian/fden_clean_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_clean_nzb.1
        install -p -m0644 ./debian/fden_create_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_create_nzb.1
        install -p -m0644 ./debian/fden_delete_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_delete_nzb.1
        install -p -m0644 ./debian/fden_grab_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_grab_nzb.1
        install -p -m0644 ./debian/fden_start_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1
        man -l --recode UTF-8 ./debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1 > debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1.dh-new
        mv debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1.dh-new debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1
        man -l --recode UTF-8 ./debian/fden-usenet/usr/share/man/man1/fden_create_nzb.1 > debian/fden-usenet/usr/share/man/man1/fden_create_nzb.1.dh-new
        mv debian/fden-usenet/usr/share/man/man1/fden_create_nzb.1.dh-new debian/fden-usenet/usr/share/man/man1/fden_create_nzb.1
        man -l --recode UTF-8 ./debian/fden-usenet/usr/share/man/man1/fden_delete_nzb.1 > debian/fden-usenet/usr/share/man/man1/fden_delete_nzb.1.dh-new
        mv debian/fden-usenet/usr/share/man/man1/fden_delete_nzb.1.dh-new debian/fden-usenet/usr/share/man/man1/fden_delete_nzb.1
        man -l --recode UTF-8 ./debian/fden-usenet/usr/share/man/man1/fden_clean_nzb.1 > debian/fden-usenet/usr/share/man/man1/fden_clean_nzb.1.dh-new
        mv debian/fden-usenet/usr/share/man/man1/fden_clean_nzb.1.dh-new debian/fden-usenet/usr/share/man/man1/fden_clean_nzb.1
        man -l --recode UTF-8 ./debian/fden-usenet/usr/share/man/man1/fden_grab_nzb.1 > debian/fden-usenet/usr/share/man/man1/fden_grab_nzb.1.dh-new
        mv debian/fden-usenet/usr/share/man/man1/fden_grab_nzb.1.dh-new debian/fden-usenet/usr/share/man/man1/fden_grab_nzb.1
        chmod 0644 -- debian/fden-usenet/usr/share/man/man1/fden_start_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_create_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_delete_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_clean_nzb.1 debian/fden-usenet/usr/share/man/man1/fden_grab_nzb.1

My release: lsb_release -rd
Description: Ubuntu 18.04 LTS
Release: 18.04

Revision history for this message
Andrew McKinlay (mckinlay-andrew) wrote :

Is your home directory on NFS? I am getting the exact same issue. Output of dmesg:

```
[4399566.994763] audit: type=1400 audit(1537967487.910:1582): apparmor="DENIED" operation="sendmsg" profile="/usr/bin/man" pid=5981 comm="man" laddr=<redacted> lport=744 faddr=<redacted> fport=2049 family="inet" sock_type="stream" protocol=6 requested_mask="send" denied_mask="send"
[4399566.995173] nfs: RPC call returned error 13

Looks like an AppArmor config issue.

Revision history for this message
Frank Denissen (aankoopdenissen) wrote :

My home directory is indeed on NFSv4.

Revision history for this message
Colin Watson (cjwatson) wrote :

This is going to be a bit tricky.

The intent of the AppArmor confinement we do is to leave /usr/bin/man itself mostly unconfined, but apply rather stricter confinement to groff-related subprocesses and decompression filters. It's easy enough to allow /usr/bin/man itself to read from the network (although it seems unfortunate that network filesystems require this; that ought to be an implementation detail). However, at the moment we have to allow decompression filters to have filesystem read access because AppArmor revalidates inherited file descriptors (which also seems an unfortunate behaviour to me), and I really don't want to grant decompressors the ability to talk to the network.

What I think we need to do is to launder the input data through the internal equivalent of a "cat" pipe before sending it to the decompressor, just to stop AppArmor from doing its annoying revalidation thing (ideally we'd only do this if AppArmor confinement is in effect, but that's an optimisation and isn't required). It would then be possible to tweak the /usr/bin/man profile and fix this bug.

Changed in man-db (Ubuntu):
status: New → Triaged
importance: Undecided → High
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

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