File_mmap of /dev/zero is currently blocked

I’ve been playing with building makemkv which is partially closed-source. The binary-only executable tries to mmap /dev/zero which is currently denied by the security system. I think this might be required to zero-out memory for use in crypto routines internal to makemkv, but that’s just a hunch. Either way makemkv will not work at all without allowing, or hijacking via LD_PRELOAD or another method, the access to /dev/zero:

= AppArmor =
Time: Jul 24 22:45:16
Log: apparmor="DENIED" operation="file_mmap" profile="snap.makemkv.makemkv" 
name="/dev/zero" pid=31990 comm="makemkvcon" requested_mask="m" 
denied_mask="m" fsuid=1000 ouid=0
File: /dev/zero (write)

This post is by way of prompting the discussion as to whether we should allow access to /dev/zero (both read and write, as it seems this particular program requires write), whether said allowance should be opt-in via a plug, or retain the current block.

2 Likes

I looked into this and essentially there are two ways to share memory without a backing file: 1) use mmap with MAP_SHARED | MAP_ANONYMOUS and 2) open /dev/zero and pass it to mmap() with MAP_SHARED. Both are valid and therefore the access should be allowed. I’ll create a PR for this.

Hmm, actually, I need to investigate this more. Everything I said before is true but the denial might be kernel specific (eg, 4.11 on Ubuntu 17.10 doesn’t have this denial regardless of method). What kernel and architecture is this on?

this is on xenial (16.04) with:

$ uname -a
Linux dllewellyn-Z170X-UD5-TH 4.10.0-27-generic #30~16.04.2-Ubuntu SMP Thu Jun 29 16:07:46 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

AMD64/X86_64

Hmm. I just checked on 12.04 - 17.04 i386, 12.04 - 17.10 amd64 and series 16 Ubuntu Core armhf (rpi2) and none of these need ‘m’ when using method 2.

I think you should strace this process so we can better understand what the application is doing. I suggest something along the lines of:

$ strace -D -f -vv -e 'open,mmap,mmap2' /path/to/thing/getting/denied

For example, when I run the above:

$ strace -D -f -vv -e 'open,mmap,mmap2' ./anon_mmap 
strace: Process 30895 attached
...
open("/dev/zero", O_RDWR)               = 3
mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0x7fdd567e7000

I’ve never managed to get strace on gui apps to work - it complains about needing to be root, and then running gui apps through sudo fails with being unable to access X display. I’ve run the makemkvcon without using the gui intermediary, though, and posted the results to http://paste.ubuntu.com/25171485/

This appears to be this kernel: https://launchpad.net/ubuntu/+source/linux-hwe. I installed this kernel in an amd64 vm (apt-get install linux-generic-hwe-16.04), rebooted and don’t see the denial.

I’ve pulled-out the two mmap lines from the very end of the strace (previous post):

mmap(NULL, 393216, PROT_READ|PROT_WRITE, MAP_PRIVATE, 3, 0) = -1 EACCES (Permission denied)
mmap(NULL, 393216, PROT_READ|PROT_WRITE, MAP_PRIVATE, 3, 0) = -1 EACCES (Permission denied)

the difference seems to be that it wants MAP_PRIVATE access

Right, if I use MAP_PRIVATE, I also don’t see the denial. Lets get a full strace. Can you do:

$ strace -D -f -vv -e '!select,_newselect,clock_gettime' -- /path/to/thing/getting/denied

here’s the pastebin. I’m just trawling through it myself: http://paste.ubuntu.com/25171738/

FYI, for those wondering about the -e '!select,_newselect,clock_gettime' arguments, please see Stracing snap commands

I talked about this with AppArmor upstream and was reminded that either PROT_EXEC would need to be specified in the mmap() call on the /dev/zero fd, or the application has the personality bit set which would cause read to also map EXEC.

Looking at the strace, I don’t see anything fishy with the PROT_EXECs and I don’t see a call to personality(). However it seems this trace was perhaps not done under confinement or done on a different binary? The only open on /dev/zero in the last paste doesn’t show an mmap() on the fd so something is different…

it’s definitely the same binary called the same as previously with different strace wrapper - the mmap is line 2118 and 2121

Yes I see now that the open is at 2040 but the two mmaps are at 2118 and 2121.

That leaves personality: I don’t see personality in this trace. Are you using setarch to invoke this program? Is it a program not compiled for Linux?

I’m not using setarch. the program, is closed source and presumably compiled for linux (else?)

this is what file tells about the binary:

/snap/makemkv/x12/usr/bin/makemkvcon: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, stripped

The next step would be to add some debugging information to the kernel. Either you can provide me with the snap and how you are invoking it, or we can provide you a debugging kernel to install. I suggest the former. If you would prefer, you can send me the snap privately (jamie at ubuntu dot com).

I’ve emailed you a link to the file. I had to link it rather than attach because gmail (my provider) doesn’t like large attachments. The file is on my Nextcloud instance.

Thanks, I have it and have reproduced the issue.

It looks like this is kernel-specific. If I try the 16.04 4.4 kernel, I don’t see the issue, but the 4.10 hwe kernel does. I’ll continue to work with AppArmor upstream on this.