Subject: Re: firejail: Unable to create a whitelisted config file

From: anonymous coward <[email-masked]>
Date: Mon, 25 Jul 2022 10:43:04 +0200

Package: firejail
Version: 0.9.64.4-2
Followup-For: Bug #1015816
X-Debbugs-Cc: [email-masked]

It was an interesting suggestion but in the end it made no
difference. And in fact the test inspires a feature request.

I created /tmp/toot.profile as follows:

===8<------------------------------
mkdir ~/my_config_files/toot/
===8<------------------------------

Then I ran the same command as previously, but added
“--profile=/tmp/toot.profile”.  It ran just the same as it did
previously, except the only difference is that ~/my_config_files/toot/
persists.  So it runs successfully, exits, and leaves the empty
directory ~/my_config_files/toot/.  The fact that it’s empty is the
problem.  The config file created therein must persist as well.

The output is the same as before apart from also printing the
following line upon launch:

===8<------------------------------
…
Reading profile /tmp/toot.profile
…
===8<------------------------------

It was useful to see an indicator that the profile was read. It’s a
little annoying that firejail does not inform the user that it’s
creating a directory.  After reading the profile, it eventually
executes “mkdir ~/my_config_files/toot/” without telling the user.  So
as a feature request I suggest printing that action in the output.

Even if the /mkdir/ parameter were to have fixed the problem, it would
have simply been a workaround.  That is, it’s not always trivial (or
even possible) to predict which directories an app will
create. Firejail should permit an app to arbitrarily create any
directories on-the-fly as needed-- to the extent that it has write
permission in the applicable directory.

In a 2nd test I took your suggestion a step further, and expanded
/tmp/toot.profile to also create the file:

===8<------------------------------
mkdir ~/my_config_files/toot/
mkfile ~/my_config_files/toot/config.json
===8<------------------------------

Firejail successfully created an empty config file, but this time it
fell over.  When I say “it” fell over, I don’t know if Firejail fell
over or if the app did. I’m speculating that the app’s JSON parser did
not like finding any empty file.  This was the output:

===8<------------------------------
Traceback (most recent call last):
  File "/usr/bin/toot", line 11, in <module>
    load_entry_point('toot==0.27.0', 'console_scripts', 'toot')()
  File "/usr/lib/python3/dist-packages/toot/console.py", line 547, in main
    user, app = config.get_active_user_app()
  File "/usr/lib/python3/dist-packages/toot/config.py", line 94, in get_active_user_app
    config = load_config()
  File "/usr/lib/python3/dist-packages/toot/config.py", line 70, in load_config
    return json.load(f)
  File "/usr/lib/python3.9/json/__init__.py", line 293, in load
    return loads(fp.read(),
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)
===8<------------------------------

I think I might have previously reported the difficulty in
distinguising an app error from a firejail error because FJ does not
tag its own output.  In any case, to summarize, I’ll enumerate the 3
outstanding issues:

1) The config file for the /toot/ app is apparently created within the
sandbox but it fails to persist when the app terminates (regardless of
whether or not the mkdir parameter is used).

2) The mkdir and mkfile profile parameters take effect (as expected),
but Firejail neglects to inform the user of this.

3) Firejail errors are often indistinguishible from child process
errors because FJ makes no effort to tag its own output.

-- System Information:
Debian Release: 11.4
  APT prefers stable-updates
  APT policy: (990, 'stable-updates'), (990, 'stable-security'), (990, 'testing'), (990, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.10.0-16-amd64 (SMP w/2 CPU threads)
Kernel taint flags: TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages firejail depends on:
ii  libapparmor1  2.13.6-10
ii  libc6         2.31-13+deb11u3
ii  libselinux1   3.1-3

Versions of packages firejail recommends:
ii  firejail-profiles  0.9.64.4-2+deb11u1
ii  iproute2           5.10.0-4
ii  iptables           1.8.7-1
ii  xauth              1:1.1-1
ii  xdg-dbus-proxy     0.1.2-2
ii  xpra               3.0.13+dfsg1-1
ii  xvfb               2:1.20.11-1+deb11u1

firejail suggests no packages.

-- Configuration Files:
/etc/firejail/firejail.config changed [not included]

-- no debconf information

---

From: anonymous coward <[email-masked]>
Date: Mon, 25 Jul 2022 11:47:34 +0200

Package: firejail
Version: 0.9.64.4-2

To cover all bases, I also tried enabling the read-write perms,
effectively running:

  $ firejail --env=XDG_CONFIG_HOME="$HOME"/my_config_files\
             --whitelist="$(readlink $HOME/.config)"toot/config.json\
             --noblacklist="$(readlink $HOME/.config)"toot/config.json\
             --profile=<(printf '%s\n' 'mkdir ~/tools/conf/toot')\
             --read-write="$HOME"/my_config_files/toot\
             --read-write="$HOME"/my_config_files/toot/config.json\
             toot login

It made no difference. It still just leaves the empty directory
"$HOME"/my_config_files/toot.

As a possible secondary bug in the docs, the man page contains:

===8<------------------------------
  --read-write=dirname_or_filename
          Set directory or file read-write. Only files or directories belonging to the current user are allowed for this  operation.
          File globbing is supported, see FILE GLOBBING section for more details.  Example:

          $ mkdir ~/test
          $ touch ~/test/a
          $ firejail --read-only=~/test --read-write=~/test/a
===8<------------------------------

The man page does not state what the default perms are.  The whitelist
option in the man page says: “Modifications to whitelisted files are
persistent”. This seems to imply that the read-write option is the
default setting on whitelisted dirs, but makes no mention of what
happens if read-write is used on a non-whitelisted dir.  The example
given somewhat implies that read-write is useful when giving different
perms to a subdir than the parent dir.  But it does not outright state
this so users are left guessing.

I should also say it’s unclear whether the noblacklist option is
useful or redundant.  Does --whitelist imply --noblacklist
automatically?  The man page should make that clear.