Using Firejail to reduce the risk of running web browsers

Posted on . Updated on .

I’ve blogged in the past about how I liked to run my normal web browser under a different user. In other words, I think web browsers are the weakest link in the security chain of every desktop and workstation computer. Browsers fix security issues with every release and are used to access, download and execute programs and other documents from untrusted sources, in a wide variety of formats. When I run a web browser, sometimes I don’t know what I’m going to be opening. It may be a malicious web page that will try to exploit a vulnerability in the browser I’m using. Using the method I described in the previous link, I could run the browser process as another user, so it cannot easily access my personal files, documents, cryptographic keys, etc. That method relied on running X11 and letting local users, or at least the user running the browser, connect to the server owned by my own user.

There’s a small risk involved in that but, more importantly, since moving to Wayland, the method to allow other users to access your display server is not as straighforward. In general, a solution involving Wayland means the web browser user needs access to some files in the XDG_RUNTIME_DIR directory, including the Wayland socket. I used filesystem ACLs for that and, in my experience, the process is error-prone and unreliable. Sometimes I’ve had to adjust the set of files, or the permissions I needed to grant to those files, and things have broken out of the blue after system upgrades. The second source of risk comes from the fact that, if you want that web browser to be able to play sounds, for example when watching a video, you also needed to give the web browser user access to your sound daemon. I mentioned a method to share your user’s PulseAudio instance with other users and an update on that when I switched from PulseAudio to PipeWire.

Today I wanted to share a simpler approach to all of this, which is running your web browser, typically Firefox, under a very restricted environment using Firejail. Firejail is an open source project, probably available from your package manager, that uses Linux namespaces, seccomp-bpf and capabilities to restrict what your web browser can do and access. Notably, it ships profiles for multiple applications either based on blocklists or, in the case of Firefox (the main use case), allowlists. When you run Firefox through Firejail, for example by running firejail firefox, the resulting Firefox process will be restricted in several ways and will not be able to access most of your home directory, except for the ~/Downloads directory and its own configuration and data directories. If, on top of that, it’s running under Wayland, it will not be able to spy on your screen and other windows unless there’s a second vulnerability available in the Wayland compositor.

The following screenshot shows the file manager and Firefox displaying the contents of the home directory. Firefox is running under Firejail and, as you can see, it does not display the whole directory contents. In fact, it’s not only not displaying every file, but also using custom versions of some of them inside its jail. For example, I don’t have a .bashrc file in my home directory and Firefox is seeing a “fake” one. The src directory you can see from Firefox is also completely restricted in contents and Firefox only sees one file in the whole hierarchy: my .gtkrc-2.0 configuration file because I have it stored in a “dotfiles” repository under src and symlinked to the final location.

Screenshot showing a file manager and Firefox running under Firejail, both displaying the home directory contents and Firefox displaying many fewer files

Since I discovered Firejail, I’ve switched to using it by default when running Firefox, ditching my ad-hoc mechanisms described in previous posts.

Feeling comfortable with Cascadia Code

Posted on .

A few years ago I blogged about switching my terminal and programming font from Terminus to Ubuntu Mono. It’s only fair, then, that I mention I’ve switched from Ubuntu Mono to Cascadia Code. I’ve been using Cascadia for many months now, probably over a year, and the experience has been great so far. The font was commissioned by Microsoft and released under the SIL Open Font License, which makes it available in the repositories of many Linux distributions. For example, it’s easily available in the official Fedora or Debian repositories.

Cascadia Code
Figure 1. Cascadia Code Specimen by Wikipedia user Smartcom5, released under CC BY-SA 4.0

When I decided to give it a try I was turned off by some inconsistencies in the shapes of some characters. In particular, the shape of the lowercase F glyph is a bit odd due to the horizontal crossing line being quite low compared to similar features in other characters. In other words, apparently Ubuntu Mono was easier on the eyes due to its simpler and more consistent shapes. However, after using it for months, I can really vouch for it. It can be used for long programming sessions comfortably, the characters are quite distinct from one another, it’s elegant and I haven’t gotten tired of it at all. Summing up its advantages:

  • The font has thick strokes, which is important to make it look good when you increase the font size for those like me that don’t see as well as they did in their youth or simply prefer to configure fonts with a larger size.

  • It’s very easy to read and doesn’t get tiring.

  • It’s released under an actual open font license, making it widely available (contrary to Ubuntu Mono).

  • The character size is more consistent with other fonts in the system, so it can be easily combined with them.

Regarding the last point, I mention it because fonts from the Ubuntu family tend to be smaller when compared to other fonts in the system. A 16pt size text containing a 16pt size Ubuntu Mono word will likely look a bit weird, with the Ubuntu Mono word being smaller than the surrounding text. Of course, the Ubuntu font family is internally consistent in this regard: if the surrounding text is also in a Ubuntu font, you won’t have this problem.

Anyway, if you haven’t had the chance, give the font a try. I’m using it now for my IDEs and terminals. Note: if you don’t like the programming ligatures (I don’t), you have several options. The easiest one is using the Cascadia Mono variant, which removes them completely.

Year-end donations round, 2022 edition

Posted on .

As I’ve explained in the past, at the end of each calendar year I always like to make a small round of personal donations to projects and organizations that are important for my personal digital life.

This year I’ve chosen the following organizations or projects:

  • EFF for their excellent work on the defense of civil liberties and digital rights. As you can see, I always try to donate to them at the end of the year.

  • Signal because I use the messaging app daily and it’s an essential tool for me. Free to use and released under an open source license. It allows me to text, call and video call my family privately.

  • Internet Archive because the Wayback Machine and other subprojects of them are incredibly appealing for the preservation of digital history and resources.

  • Pi-hole because I have it installed on a RPi4 on my local network and it helps me keep unwanted content at bay for multiple devices, including the ones that have no built-in filters.

  • andOTP because I use it daily. Note the project has been archived this year and the author is recommending users to move to alternative projects like Aegis Authenticator. Still, I have not migrated yet and I’ve been using the app for multiple years, so I felt my duty was to donate.

  • RPM Fusion because I’ve been using their packages for several years and they’re great for saving a lot of time in my Fedora systems. I don’t need to spend much time compiling and packaging some pieces of software myself. Special mention to their NVIDIA driver packaging, their chromium-freeworld version of Chromium as well as several tools in my multimedia toolchain, like mpv and ffmpeg.

NVIDIA and Wayland on Fedora 37

Posted on .

Starting with Fedora 36 it’s been possible to run Gnome using Wayland on NVIDIA cards. The experience was not perfect. Some programs, like the mpv media player, had notable display issues and had to be forced to launch in X11 mode, using XWayland. However, the experience has been improving steadily and with Fedora 37 I haven’t found any major drawbacks to running Wayland on my NVIDIA system. Notably, even Firefox works using Wayland, and WebGL apps or Google Maps run in hardware acceleration mode.

Desktop recording of Gnome running Firefox on Wayland with an NVIDIA GTX 1070 card

Recent versions of mpv no longer display a black screen when running on NVIDIA cards, and I haven’t found any issues with other apps, but your mileage may vary. If you have an NVIDIA card and are interested in running Wayland, give it a try: it may simply work. Yes, the path to get here hasn’t been easy, and the GBM vs EGLStreams situation was and is a pity. Still, however we arrived to the present day, what’s important is that we’re here and we have what we have.

If you find any issues running some applications in Wayland mode, you can try running them on X11 instead to see if that fixes the problem. The mechanism to do so varies a bit by application and toolkit. For example, for mpv you could use --gpu-context=x11 or stick the option in the config file. For some Qt apps like KeePassXC you can run them with export QT_QPA_PLATFORM=xcb. Chromium-based browsers do not respect the “large text” accessibility option in Gnome, which changes screen scaling, and need to be run in X11 mode if you use that option (Google Chrome does that by default, but chromium-freeworld from RPM Fusion tries to use Wayland by default). For them, you can unset WAYLAND_DISPLAY and export XDG_SESSION_TYPE=x11. This last mechanism is pretty generic and may work for other apps as well.

Note: as for the NVIDIA drivers, I’m running the RPM Fusion packages for convenience and because it’s the easiest way. The only notable problem I have is the need to reinstall those packages when I upgrade Fedora versions, like when I jumped from Fedora 36 to 37.

Despite these recent improvements, it’s likely I’ll switch to an AMD GPU and CPU for my next desktop computer. Both my current CPU (i7-4770k) and GPU (GTX 1070) are already a bit dated and I expect less issues running Linux if I switch to an all-AMD system. The gaming experience on Windows may not be as good, I’m not sure, but I spend most on my time on Linux so I prefer to have a better-supported system there with open source drivers.

Vulkan extensions Igalia helped ship in 2022

Posted on .

Filed under: igalia

Igalia Logo next to the Vulkan Logo

The end of 2022 is very close so I’m just in time for some self-promotion. As you may know, the ongoing collaboration between Valve and Igalia lets me and some of my colleagues work on improving the open-source Vulkan and OpenGL Conformance Test Suite. This work is essential to ship quality Vulkan drivers and, from the Khronos side, to improve the Vulkan standard further by, among other things, adding new functionality through API extensions. When creating a new extension, apart from reaching consensus among vendors about the scope and shape of the new APIs, CTS tests are developed in order to check the specification text is clear and vendors provide a uniform implementation of the basic functionality, corner cases and, sometimes, interactions with other extensions.

In addition to our CTS work, many times we review the Vulkan specification text from those extensions we develop tests for. We also do the same for other extensions and changes, and we also submit fixes and improvements of our own.

In 2022, our work was important to be able to ship a bunch of extensions you can probably see implemented in Mesa and used by VKD3D-Proton when playing your favorite games on Linux, be it on your PC or perhaps on the fantastic Steam Deck. Or maybe used by Zink when implementing OpenGL on top of your favorite Vulkan driver. Anyway, without further ado, let’s take a look.

VK_EXT_image_2d_view_of_3d

This extension was created by our beloved super good coder Mike Blumenkrantz to be able to create a 2D view of a single slice of a 3D image. It helps emulate functionality which was already possible with OpenGL, and is used by Zink. Siru developed tests for this one but we reviewed the spec and are listed as contributors.

VK_EXT_shader_module_identifier

One of my favorite extensions shipped in 2022. Created by Hans-Kristian Arntzen to be used by Proton, this extension lets applications query identifiers (hashes, if you want to think about them like that) for existing VkShaderModule objects and also to provide said identifiers in lieu of actual VkShaderModule objects when creating a pipeline. This apparently simple change has real-world impact when downloading and playing games on a Steam Deck, for example.

You see, DX12 games ship their shaders typically in an intermediate assembly-like representation called DXIL. This is the equivalent of the assembly-like SPIR-V language when used with Vulkan. But Proton has to, when implementing DX12 on top of Vulkan, translate this DXIL to SPIR-V before passing the shader down to Vulkan, and this translation takes some time that may result in stuttering that, if done correctly, would not be present in the game when it runs natively on Windows.

Ideally, we would bypass this cost by shipping a Proton translation cache with the game when you download it on Linux. This cache would allow us to hash the DXIL module and use the resulting hash as an index into a database to find a pre-translated SPIR-V module, which can be super-fast. Hooray, no more stuttering from that! You may still get stuttering when the Vulkan driver has to compile the SPIR-V module to native GPU instructions, just like the DX12 driver would when translating DXIL to native instructions, if the game does not, or cannot, pre-compile shaders somehow. Yet there’s a second workaround for that.

If you’re playing on a known platform with known hardware and drivers (think Steam Deck), you can also ship a shader cache for that particular driver and hardware. Mesa drivers already have shader caches, so shipping a RADV cache with the game makes total sense and we would avoid stuttering once more, because the driver can hash the SPIR-V module and use the resulting hash to find the native GPU module. Again, this can be super-fast so it’s fantastic! But now we have a problem, you see? We are shipping a cache that translates DXIL hashes to SPIR-V modules, and a driver cache that translates SPIR-V hashes to native modules. And both are big. Quite big for some games. And what do we want the SPIR-V modules for? For the driver to calculate their hashes and find the native module? Wouldn’t it be much more efficient if we could pass the SPIR-V hash directly to the driver instead of the actual module? That way, the database translating DXIL hashes to SPIR-V modules could be replaced with a database that translates DXIL hashes to SPIR-V hashes. This can save space in the order of gigabytes for some games, and this is precisely what this extension allows. Enjoy your extra disk space on the Deck and thank Hans-Kristian for it! We reviewed the spec, contributed to it, and created tests for this one.

VK_EXT_attachment_feedback_loop_layout

This one was written by Joshua Ashton and allows applications to put images in the special VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT layout, in which they can both be used to render to and to sample from at the same time. It’s used by DXVK 2.0+ to more efficiently support D3D9 games that read from active render targets. We reviewed, created tests and contributed to this one.

VK_EXT_mesh_shader

I don’t need to tell you more about this one. You saw the Khronos blog post. You watched my XDC 2022 talk (and Timur’s). You read my slides. You attended the Vulkan Webinar. Important to actually have mesh shaders on Vulkan like you have in DX12, so emulation of DX12 on Vulkan was a top goal. We contributed to the spec and created tests.

VK_EXT_mutable_descriptor_type

“Hey, hey, hey!” I hear you protest. “This is just a rename of the VK_VALVE_mutable_descriptor_type extension which was released at the end of 2020.” Right, but I didn’t get to tell you about it then, so bear with me for a moment. This extension was created by Hans-Kristian Arntzen and Joshua Ashton and it helps efficiently emulate the raw D3D12 binding model on top of Vulkan. For that, it allows you to have descriptors with a type that is only known at runtime, and also to have descriptor pools and sets that reside only in host memory. We had reviewed the spec and created tests for the Valve version of the extension. Those same tests are the VK_EXT_mutable_descriptor_type tests today.

VK_EXT_extended_dynamic_state3

The final boss of dynamic state, which helps you reduce the number of pipeline objects in your application as much as possibly allowed. Combine some of the old and new dynamic states with graphics pipeline libraries and you may enjoy stutter-free gaming. Guaranteed!1 This one will be used by native apps, translation layers (including Zink) and you-name-it. We developed tests and reviewed the spec for it.

1Disclaimer: not actually guaranteed.