First of all, I’d like to do some basic defining:
What is FireJail? It’s a type of sandboxing program, which can be run from the command-line, and which allows users to run certain programs which they do not trust, even with user-level access to their Linux computers.
What is an AppImage? It’s a special kind of file, that has execute permissions set, but that is also linked to its own, local version of many libraries, thereby circumventing compatibility issues. But, the way an AppImage is made, consists of a file-system image, that the kernel actually needs to mount, within which these libraries and executables exist, and that gets mounted read-only by default. The security of the computer really depends, on the kernel making sure, that none of the files in this virtual FS can be mounted, with their SETUID bits taking effect. (:1) (:2)
However, even under Linux, there is some risk in ‘arbitrary code’ running with the username of the person who caused this, since most of that user’s personal data is also stored under his or her username. Further, modern Linux computers sometimes ask for requests coming from user-space, resulting in actions by the O/S, and with elevated privileges.
The problem in running certain AppImage’s using FireJail is the fact that the most recent AppImage’s use ‘SquashFS’ as their (compressed) image, while older AppImage’s used an ISO container, which did not offer (much) compression. The version of FireJail that I can install under Debian 9 / Stretch is still of a variety, that can only run AppImage’s built with ISO Images, not with SquashFS. The following bulletin-board posting correctly identified the problem, at least for me:
Following what was suggested there, and wanting this to work, I next uninstalled the version of FireJail that ships with my distro, and cloned the following repository, after which I custom-compiled FireJail from there:
I got version 0.9.63 to work, apparently fully.
This latest version of FireJail does in fact run my AppImage’s just fine. Not only that, but now I can know that other, more recent AppImage’s can also be run with FireJail (on my main computer).
If people want to obtain the accompanying GUI, then the way to do that is, to custom-compile the accompanying ‘firetools’ project:
This parallels how the Debian ‘firetools’ package enhances the Debian ‘firejail’ package…
But, if people are only willing to use the version of FJ that comes with their package manager, then my AppImage’s will never run, for the reason I just explained.
When running AppImage’s using FireJail, one precedes the name of the AppImage with the ‘
--appimage‘ command-line option, because they are a special case.
(Updated 8/29/2020, 13h05: )
The way the virtual mount takes place uses system calls, and parallels how FUSE would work. FUSE in turn, is a program that already allows the user to mount file-systems, without requiring root privileges. AppImage does not use FUSE, because, if a SquashFS-based AppImage is being run, binary code within it uses the ‘squashfs’ kernel module, which the target computer must possess. If FUSE was being used, then the implementation of the file system would be in user-space code, and not, in kernel-space code. But, many of the same security issues arise.
I happen to have a utility installed, which is called ‘squashfuse‘, and which ignores the kernel module, and which uses FUSE to mount a SquashFS File System Image. I installed this utility from a custom-compile; it is not a standard part of Debian Stretch.
What I will do below is highlight a security issue that could exist, when a SquashFS image is mounted by a user, without elevated privileges. I have created the sub-folder ‘Roots_Dirk_Mittler’, and I have prepared it, by setting the SETUID bit of the file ‘roots.cpp’. It’s a file chosen for demonstration purposes. In fact, it cannot be executed, because it’s a source file. In theory, if the file could be executed, then the user who did so would next become user ‘dirk’ for the purpose of doing so, obtaining UID=1000 on my machine specifically. Then, I have used the (user-space) ‘mksquashfs’ utility, to pack that entire folder into the image file called ‘dir.sqsh’, with the ‘
-all-root‘ command-line option. This is commonly done, and means that, once mounted, all the files will be owned by root. It sets the UIDs to zero, thereby avoiding certain other issues that could result (and that have resulted, with earlier versions of ‘appimagetool’). Finally, I mounted ‘dir.sqsh’ using my ‘squashfuse’ command…
What this has done is, to create a file which is ‘SETUID root’! But, I never became root to do so:
Traditionally, this type of situation would have set off alarm bells in System Administrators’ minds, because now, if that file was in fact executable, and, executed by any user, it would run with elevated privileges. However, the following screen-shot of a man-page, explains why this is not really a problem:
What the highlighted text explains is that, by default, FUSE mounts with the ‘nodev’ and ‘nosuid’ options. And, even though files are being displayed as though having the SETUID bit set, it does not take effect. Therefore, a security breach has not just taken place.
In general, under Linux, If a specific file-system has been mounted with its own security constraints, those may not be indicated or overridden, by the permission bits that individual entries are listed with.
Well, the way it works when an AppImage mounts a file system, without actually using FUSE, is probably parallel to this.
This can cause certain programs to malfunction, as documented blow:
Even though these types of error messages are being complained about, in my opinion, they do not constitute errors, but rather, display a security feature built-in to the kernel. Certain applications that can run, when installed from the package manager, have their own, internal sandboxes, and this includes certain Web-browsers, such as, notably, Chrome. These applications possess a sandbox helper program, which installs with SETUID root, but the only purpose of which is, to sandbox what certain extensions (in the most common case, of Chrome) can do. Creating this sandbox requires root, so, Chrome elevates a part of itself to root, just to create this sandbox.
This should not work when Chrome is being run from an AppImage, because, even if the developer tried to make the sandbox helper SETUID when he or she packaged the AppImage, once it gets mounted, its SETUID property does not take hold! And this is why those types of error messages are so common.
Some applications accept the ‘
--no-sandbox‘ flag, so that the error message can be made to go away. But then, many applications do not contain the specific code that would need to be supplied by their developer, to run, without sandboxing anything.
Long story short, what all this means is, that the Linux kernel team is keeping our computers secure.
When the ‘mksquashfs’ utility is run, and an already existing SquashFS image file chosen as output, the newly specified file system will be appended to the existing one. If the same file system was appended to the image for a second time, it will cause all the entries in the root directory of the virtual, mounted file system to receive a duplicate, the name of which is the original name, followed by a ‘_1′. If the same FS is squashed to the image a third time, names that end with ‘_2′ will be auto-generated. This is a usage error to look out for.
Now, I suppose that the reader might next ask, ‘Why did Dirk install squashfuse, when in fact he does have the kernel module installed, and could just become root, and then use a regular mount command, to mount his SquashFS images?’
The answer to that question lies in the fact that, although I’d estimate the kernel module to be more reliable in how it works, to keep its code small, the kernel team may not have included support for all the compression forms that SquashFS will more generally offer, such as ‘lzo’ and ‘xz’. These compression forms may ultimately be more interesting to play with, than the default ‘gzip’, because ‘xz’ specifically offers better compression than what even ‘bzip’ would offer, and is ‘slow and heavy to compress, but lightweight and fast to decompress’. These are ideal characteristics for read-only file-system images.
I can just imagine that the developers behind AppImage may be experimenting with using ‘xz’ as their compression form, doing everything right, but consistently obtaining non-runnable AppImage’s, just because the kernel modules on certain computers don’t support ‘xz’. In such a case, I can also not just instruct the AppImage in question to use my ‘squashfuse’ utility, because the AppImage has specifically been coded to use the kernel module.
But, if I want, I can play with SquashFS images that were compressed with ‘xz’, for my own purposes.
What some sources on the Web have already pointed out is the fact, that even though the SquashFS file-system itself will be mounted read-only, if actually used to source a tiny O/S, it needs to be made writable. And,
As already explained elsewhere, the way to do that, is to perform a second mount, this time creating an Overlaid file-system, so that writing to this FS will cause the changes to be written to an ‘Upper FS’, that is not of the type SquashFS, while original data is still being supplied by the ‘Lower FS’, that is read-only.
What could become confusing about some of the articles on the Web that explain this, is the fact that sometimes, those articles will assume that ‘auFS’ is to be used, or even ‘UnionFS’, when in fact, as of kernel version 3.18, the better way to accomplish this, is by using ‘OverlayFS‘. This is also available under Debian / Stretch at the time I’m writing this. These are all solutions that aim to do the same thing, the only problem being that the older file-systems that do this, are twice-outdated and bit-rotted. So please, do yourself the favour and use ‘OverlayFS’, if it’s available.