File_mmap of /dev/zero is currently blocked

thanks for looking into it :slight_smile:

Ok, as it turns out the 4.10 kernel is behaving correctly and other kernels should be denying the ‘m’ on /dev/zero. Those kernels will likely get an update to fix this.

The problem stems from the fact that usr/bin/makemkvcon has the READ_IMPLIES_X personality bit set. This can be seen with:

$ readelf -lW usr/bin/makemkvcon|grep GNU_STACK
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

(notice how ‘E’ is listed). When this bit is set, read access implies execute, and ‘m’ is a special form of execute (from ‘man apparmor.d’: ‘allow PROT_EXEC with mmap(2) calls’) and because we only have ‘/dev/zero rw’, you see the denial. Previously when we looked at the mmap()s in the strace while we only saw PROT_READ and PROT_WRITE, because the personality bit was set, PROT_EXEC was added under mediation. This personality is very problematic on the whole, because it changes the requirements of the permissions and in trying to meet those requirements, it can substantially weaken the policy (eg, normally you ‘read’ or ‘read and exec’ or ‘read and write’, but not ‘read, write and exec’).

In this very particular case, allowing ‘/dev/zero m’ would not be a problem, because ‘man zero’ tells us that writes to /dev/zero are simply discarded by the kernel. However, because the program has an executable stack, there is nothing saying that after we fix /dev/zero something else won’t pop out needing x or m permissions when it shouldn’t. In the future, AppArmor will have language something along the lines of ‘allow read_implies_x’ which, when the personality bit is set, it will add ‘x’ implicitly to any read rules. This is not a solution because it merely makes it easier to allow weakened, workaround policy (it is conceivable it could be in a separate snappy interface though).

I suggest approaching upstream and pointing them at https://wiki.ubuntu.com/SecurityTeam/Roadmap/ExecutableStacks so they can improve their code. Currently their code is vulnerable to stack memory attacks and fixing this will meaningfully improve their code everywhere. It just so happens it would also make the ‘m’ denial go away.

so, for the near-term “get it working” I’ve added a call to execstack -c $binary and we’re getting closer now. it doesn’t die with the m request on /dev/zero. Now I’m onto getting the qt frontend to load, which is complaining about:

Qt: Session management error: None of the authentication protocols specified are supported

replying to myself, the Session management error from qt is a non-error unrelated to the continued failure. The GUI app which is open source calls into the closed-source makemkvcon CLI program which in turn tries to create an entry at /dev/shm/makemkvshm???? where the question marks are random. Because it’s a closed source binary I’m fairly sure it isn’t possible to move the shared memory device easily, so I’m stuck on getting the UI working, but at least the CLI works correctly excepting the shared memory interface which is only triggered when the GUI interacts with it.

I suggest taking a look at the snapcraft preload part: https://github.com/sergiusens/snapcraft-preload

totally rename that repo to “PaaS”: Preload as a Service :-p

rightio, the preload helper did fix one instance of shm file access, but it missed a second one:

strace:

[pid  4491] statfs("/dev/shm/", {f_type=TMPFS_MAGIC, f_bsize=4096, f_blocks=4112293, f_bfree=4112189, f_bavail=4112189, f_files=4112293, f_ffree=4112188, f_fsid={0, 0}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV}) =0
[pid  4491] futex(0x7f49c4594310, FUTEX_WAKE_PRIVATE, 2147483647) = 0
[pid  4491] unlink("/dev/shm/snap.makemkv.makemkvshm118b") = -1 ENOENT (No such file or directory)
[pid  4491] open("/dev/shm/snap.makemkv.makemkvshm118b", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0777) = 12
[pid  4491] ftruncate(12, 65816)        = 0
[pid  4491] mmap(NULL, 65816, PROT_READ|PROT_WRITE, MAP_SHARED, 12, 0) = 0x7f49c4ea6000
[pid  4491] unlink("/dev/shm/snap.makemkv.sem.makemkvsem0118b") = -1 ENOENT (No such file or directory)
[pid  4491] lstat("/dev/shm/F8dPa9", 0x7ffff25ee280) = -1 ENOENT (No such file or directory)
[pid  4491] open("/dev/shm/F8dPa9", O_RDWR|O_CREAT|O_EXCL, 0777) = -1 EACCES (Permission denied)
[pid  4491] pwrite64(4, "csf4\n", 5, 125) = 5
[pid  4491] fsync(4)                    = 0
[pid  4491] pwrite64(4, "csf1\n", 5, 130) = 5
[pid  4491] fsync(4)                    = 0

relevant deny from snappy-debug scanlog:

= AppArmor =
Time: Jul 31 16:35:40
Log: apparmor="DENIED" operation="mknod" profile="snap.makemkv.makemkv" name="/dev/shm/F8dPa9" pid=3087 comm="makemkvcon" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
File: /dev/shm/F8dPa9 (write)
Suggestion:
* adjust program to create files and directories in /dev/shm/snap.$SNAP_NAME.*

snappy-debug is giving the right advice here, but you might be able to adjust the preload part for this to. I suggest filing a bug or, if you are able, a PR against the preload plugin for this.

A Qt app can work just fine despite this error message:smiley:. I have released QJoyPad a while ago on the Snap Store and it has the same error message and all its features seem to be intact:smiley:.

This is of course not to say that this applies to all Qt apps, just that it’s possible.

But at the same time it’s best to fix all errors and even warnings that are screaming at you because they can lead to unexpected behavior either in a different environment or in the future:sweat_smile:.

BTW thanks for the execstack -c $binary trick! It helped me to release an ePSXe Snap:smiley:.