canvas.createContext("webgl") returns null in Electron

@jdstrand In short, that solved my problem. Thanks.

In long, I was able to run

watch -n 1 execstack -c ./dist/linux-unpacked/polarr

when snapping my application with electron-builder and was lucky enough that the execstack bit got cleared between when electron-builder produced the binary and primed it into the snap.

Is this a problem with electron-builder or just the way I’m using it? How do I set up the build in a correct way to not have execstack set?

When I boot into my Ubuntu 17.10 partition and run the same snap that I built and had work on 16.04, I once again fail to get a webgl context. The only notable difference is that I no longer get an nvidia message in the snappy-debug.security log. There is still the one log about bluez, but I would guess that that isn’t preventing webgl from working.

If I install the app’s dependencies (libgconf-2-4 and libvips42) and run the binary in the linux-unpacked directory directly, it works fine. It also works when I use electron-packager to package the app as a deb and then install that.

I’m not sure what to do now since there’s nothing in the snappy-debug.security log for me to fix but the app works iff not snap.

That’s a great question. It would be fantastic for someone in the electron community to look into this. It shouldn’t be needed (eg, chromium from Ubuntu and chrome from Google don’t have executable stacks). Snapcraft could make this easier (see my comment here: AppArmor denial for /dev/nvidiactl, but ideally it would be fixed in the electron build process.

I see on AppArmor denial for /dev/nvidiactl that electron builds occasionally have binaries with executable stacks. I have dlib and libraw C++ nodejs addons, so I use npm rebuild and node-gyp rebuild:

ELECTRON_VERSION="1.8.1";

npm rebuild \
  --runtime=electron \
  --target=${ELECTRON_VERSION} \
  --disturl=https://atom.io/download/atom-shell \
  --build-from-source
cd dlib
node-gyp rebuild \
  --runtime=electron \
  --target=${ELECTRON_VERSION} \
  --disturl=https://atom.io/download/atom-shell \
  --build-from-source
cd ..
cd libraw
node-gyp rebuild \
  --runtime=electron \
  --target=${ELECTRON_VERSION} \
  --disturl=https://atom.io/download/atom-shell \
  --build-from-source
cd ..

Since I’m using npm rebuild, am I responsible for configuring npm and gyp so that they don’t produce binaries with executable stacks? Or is electron responsible for the way that it npm rebuilds to not have an executable stack? When I get home I’ll try using a version of electron other than 1.8.1 to see if it produces an binary without an executable stack.

I tried a variety of Electron versions electron versions

npm install --save electron@1.7.1 && find node_modules/electron/ | xargs execstack 2>/dev/null | grep X 
npm install --save electron@1.2.1 && find node_modules/electron/ | xargs execstack 2>/dev/null | grep X 
npm install --save electron@1.2.0 && find node_modules/electron/ | xargs execstack 2>/dev/null | grep X 
# ... etc ...

All revisions that existed had an execstack for node_modules/electron/dist/electron. In total, I tried 1.7.1, 1.2.1, 1.2.0, 1.3.0, 1.5.0, 1.5.1, 1.5.1, 1.5.2, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8, 1.6.9, 1.6.10, 1.7.7, 1.7.8, 1.7.9, and 1.8.1.

I tried clearing execstack on 1.4.3 with

watch -n 0.1 execstack -c ./dist/linux-unpacked/polarr

and that version also lacked WebGL support.

I’ve created a simple electron WebGL app for testing. It supports WebGL when run with npm start but does not support WebGL when run as a snap:

Can I get an ETA on WebGL support in Snap? Electron is listed as a supported language in the Electron docs https://docs.snapcraft.io/build-snaps/electron. At this time, there is no way to publish Electron WebGL applications to the Ubuntu Store since .deb isn’t allowed anymore and WebGL doesn’t work in Snap yet. If WebGL Snap support is going to take a long time that’s okay, but if that’s the case I would like for the deb that I’ve packaged to go into the Ubuntu Store in the interim.

@oSoMoN - is this something you could help with? I looked at the chromium snap which doesn’t have any executable stack binaries and put in chrome://gpu and it lists WebGL as available on my 17.10 Intel system (I don’t have an nVidia system).

What is the output of snap version? If it isn’t 2.30 or higher, can you try with the snap from beta (sudo snap refresh core --beta)?

If you launch the snap from a terminal, what are the differences with the terminal output between devmode and strict?

If you install the snap with an executable stack, and then you add this to /var/lib/snap/apparmor/profiles/snap.polarr.polarr:

  /dev/nvidiactl m,

then run sudo apparmor_parser -r /var/lib/snap/apparmor/profiles/snap.polarr.polarr, then rerun your application, does it make a difference (I don’t expect it will, but it will definitively rule out execstack)?

Does stracing the snap reveal anything interesting? Note that sometimes it is handy to compare an strace from running in devmode and running in strict mode.

I tried these two suggestions with the electron-snap-webgl test app above and was still unable to get a webgl context.

strace snap run webgl (devmode): https://drive.google.com/open?id=1oQbv_53yjyP0l3egQgZi2ZKIkGG4o5we
strace snap run webgl (strict): https://drive.google.com/open?id=1pSQYqAspKEeMQ6-Y_jegX-weIP-z53Ss
The app crashes before producing a GUI when run with strace. You can diff those two files, and the diffs line up pretty well. Right before the crash in strict mode, the electron app tries to access the .Xauthority file in my home directory and is denied, but it is able to access that file in devmode and continues running:

access("/home/amiller/.Xauthority", R_OK) = -1 EACCES (Permission denied)

I’ll update my Apparmor for the webgl test to see if the deny on the .Xauthority file is what’s causing the Electron GPU process to exit with code 1024.

I changed the permissions so that the webgl snap would be able to access the .Xauthority file in my home directory in strict mode. This had the effect of making the snap not die on startup with strict mode (it never died in devmode), but it did not make webgl work in the snap when the snap continued to run.

This is the log of the webgl snap when run with read permissions granted on /home/amiller/.Xauthority:

Does publicly posting these strace logs pose a security risk to me, and if so, what do I need to do to re-secure my system?

Do you need any additional information from me to make WebGL work in Electron when packaged with Snap?

If your snap needs to access ~/.Xauthority, then you should plugs the ‘x11’ interface. If your snap is plugging the x11 interface and you have no logged security denials, I suspect your ~/.Xauthority file may have incorrect ownership (eg, root:root 0600).

Looking at the strace, it seems you are running your snap under sudo without the -H option which would explain the ~/.Xauthority denial: the snap is running with uid 0 but the /home/amiller/.Xauthority file is owned by your uid, and appamror is enforcing owner match. What happens if, after adjusting the permissions on ~/.Xauthority as necessary, you run the snap as non-root or you run the snap as root with ‘sudo -H …’?

Also, you should be seeing security denials in the logs, but haven’t posted them. Can you paste the output of journalctl | grep audit for any denials after trying the above (alternatively, you can run sudo journalctl --output=short --follow --all | sudo snappy-debug.security scanlog and paste the output after trying the above).

They shouldn’t be a problem unless you are doing something like putting sensitive items in your environment, accessing file paths you’d rather not have people know, etc. If you are going to paste, you might choose to clean them up a bit by either picking the syscalls you know you are interested in (hard to know in this case) or to remove ones that are noisy. Eg, you might also exclude: recvmsg,poll,writev.

I noticed your root running process trying to access pulseaudio files in /run/user/1000/… which would also be disallowed which certainly might cause your snap to misbehave.

I was only running as root so that I could run strace. The application wouldn’t normally be run as root and it doesn’t die on .Xauthority when not run as root.

Thanks for clarifying that.

In short, @mborzecki’s initial suggestion to add /dev/nvidia* rwm, does make WebGL work in an Electron snap. If this change didn’t cause security problems and were to be accepted, I could go ahead and publish Polarr to the snap store.

==Work==
I tried this

and the only denial I got was

Time: Dec 20 14:52:28
Log: apparmor="DENIED" operation="dbus_method_call"  bus="system" path="/" interface="org.freedesktop.DBus.ObjectManager" member="GetManagedObjects" mask="send" name="org.bluez" pid=7676 label="snap.webgl.webgl" peer_pid=1142 peer_label="unconfined"
DBus access

= AppArmor =
Time: Dec 20 14:52:28
Log: apparmor="DENIED" operation="file_mmap" profile="snap.webgl.webgl" name="/dev/nvidiactl" pid=7807 comm="webgl" requested_mask="m" denied_mask="m" fsuid=1000 ouid=0
File: /dev/nvidiactl (mmap)
Suggestion:
* verify program isn't using an executable stack: https://forum.snapcraft.io/t/snap-and-executable-stacks/1812

which made me think that I did this wrong:

Adding /dev/nvidiactl m, near the end of the file didn’t help, but then I tried

and that gave me WebGL in both the test “webgl” snap and the “polarr” snap in snap versions both 2.30 and 2.28 whereas they didn’t have WebGL before. I thought that you meant that adding /dev/nvidiactl m, was a better or more correct way of changing /dev/nvidia* rw, to /dev/nvidia* rwm, but I was mistaken and might have saved a lot of time by trying mborzecki’s suggestion first.

You can use sudo strace -u <your username> ... (this is described in the other forum post.

Was this needed after clearing the executable stack? When you cleared it, I thought you said you had no denials…

Also, can you provide an electron snap somewhere that points at chrome://gpu?

Here is an electron snap that points to chrome://gpu/.

When I cleared execstack on the binary that electron-builder produced before snapping it, I didn’t get any denials but webgl didn’t work when the snap was installed and run with strict confinement. Can clearing the execstack on a binary make it not function as it did before?