Quite a few Whonix issues after recent update

Hi,

I updated Whonix gateway and workstation 17 templates. Just regular update of all templates.

After rebooting, I notice the following:

  • sys-whonix: Restart Tor no longer works (shows error)
Command 'leaprun acw-tor-control-restart' failed.

stderr: ERROR: Could not connect to privleapd!
  • sys-whonix: systemcheck shows errors (related to prilveapd and leaprun)

  • Tor Browser no longer starts in a whonix-workstation-17 based AppVM. It starts only in DispVM. Trying from AppVM (clean, cloned from the original untouched one coming with Whonix 17) shows errors, also related to prilveapd and leaprun).

While looking for a solution, I found some posts by @marmarek on Whonix forum reporting other recent issues. I am not clever enough to figure if they are about the same thing.

I am trying to understand:

  • Am I the only one experiencing this? (i.e. is it me or who is it)
  • Is this Qubes-related or purely Whonix issue?
  • What is the right action, considering this?
1 Like

Can’t confirm that. Both templates (gateway and workstation) updated just a few minutes before. In both templates debian and whonix repositories are enabled (the stable ones).
Systemcheck works in sys-whonix and the tor browser starts as expected in whonix-workstation based qube.
During update i recognized, that in both whonix templates there are some changes in user management. So, for example, whonix has its own passwordless root mechanisn, so qubes passwordless_root package is no longer required.
See also Strong Linux User Account Isolation
It looks like Marek from Qubes team was involved in the discussion there also.

1 Like

FYI @adrelanos

1 Like

These were already sorted out earlier during development. Should be not applicable / unrelated.

At time of writing, privleap is only used by Kicksecure, Whonix.

Probably easier to use the new Template (even if “formally” testing) than attempting to debug this, which I expect to require a lot of back and forth.

See also:

2 Likes

@adrelanos

Thank you for the feedback.

Probably easier to use the new Template (even if “formally” testing) than attempting to debug this, which I expect to require a lot of back and forth.

That is exactly what I did meanwhile. However, I am facing some challenges with the new (to me) lack of passwordless root. Could you please clarify:

  • When was it introduced?
  • Why? (considering the well-known Qubes “WTF” doc)

I understand you have links with long readings for everything but a short answer would be very much appreciated, as I already looked at quite a few of those long docs and the only result is that I got lost.

Another thing: I tried passwordless-root in a test AppVM but something is not right as I still get the permission denied error upon sudo su -. I notice that this bash script modifies /rw/config/rc.local, however I tried to run that rc.local (as user), I get:

visudo: /etc/sudoers.d/nopassword: Permission denied

For the sake of testing, I restarted the AppVM but the result is still the same. I explicitly checked:

[workstation root ~]# cat /etc/sudoers.d/nopassword                   
user ALL=(ALL:ALL) NOPASSWD:ALL

However:

[workstation user ~]% sudo su -          
zsh: permission denied: sudo

I have some scripts of my own which I place in /rw/config/rc.local and some of them have a few sudo lines, so I need passwordless sudo on boot only. What is the correct way to have passwordless sudo until all /rw/config/ scripts complete and then disable it (e.g. through a /rw/config/99-disable-passwordless-root)? I guess this is related to your issue and might be a workaround for it until something better comes up.

2 Likes

I think, your questions are already answered.
Please read the docu, following the links provided by @adrelanos
Then you will see, that you can get back the old behaviour of sudo described here:

Please note the part “#Kicksecure_for_Qubes”
As far as i understand the documentation, that is the solution, that you searching for.

2 Likes

A few correct ways:

That should work, because /rw/config/rc.local runs as root. And root is still allowed to use sudo.

Btw using sudo isn’t required when using /rw/config/rc.local, except when using sudo -u / --user=. And that should still work.

For other issues:

  • Main development: December 2024 - May 2025.
  • Stable release: 17.3.9.9 / 14 May 2025

I’ve been writing about this topic since 2014.
(Free account unfortunately needed to read wiki history.)

Actually, I was of a similar opinion back then as seen in wiki history.

I’ve been learning more about the topic since. Notably, learning about Android verified boot; presentation Honey, I Shrunk the Attack Surface – Adventures in Android Security Hardening. In result, I changed my opinion.

The laymen summary is: Because it’s more secure.

Slightly more technical argument is:

Non-root enforcement is the industry standard for Android, iOS and any locked down Linux based operating system.[1]

The technical arguments are lengthy, cannot really be summarized but can be found here:

I consider this a bug: Qubes vm-sudo documentation write-up against sudo passwords inside App Qubes outdated · Issue #8823 · QubesOS/qubes-issues · GitHub

Kinda separate. Nice to have but not the best solution for the use case “only root access during boot”.

For background:

As long as user-sysmaint-split is installed, limited users (such as account user) do not have permission to execute sudo (and similar tools). This is because executable Linux file permissions ("chmod +x") [2][3] is lacking by design. Documented here: No Access to Privilege Escalation Tools for Limited Accounts

That’s why sudo configuration is ineffective.[4]

(To restore the executable permission, enable unrestricted admin mode (which is a fancy way to say, follow the documented procedure to uninstall package user-sysmaint-split.)



  1. Qubes vm-sudo documentation write-up against sudo passwords inside App Qubes outdated · Issue #8823 · QubesOS/qubes-issues · GitHub ↩︎

  2. In other words, “sudo chmod o+x /usr/bin/sudo” is omitted by design. ↩︎

  3. Yet in other words, what package user-sysmaint-split is doing effectively is: “sudo chmod o-x /usr/bin/sudo” [4] ↩︎

  4. Reliable because that’s done with SUID Disabler and Permission Hardener. ↩︎

5 Likes

@adrelanos

Thank you!

Could you clarify one more thing please:

  • Why is zsh the default shell?
  • What is the correct way to set bash as default shell?

Currently, I set in /rw/config/rc.local:

usermod --shell /usr/bin/bash $(id -un 1000)
usermod --shell /usr/bin/bash $(id -un 0)

However, whenever I start the AppVM, I get a strange result: root uses bash but user still uses zsh, regardless of:

root@host:~# grep user /etc/passwd 
user:x:1000:1000::/home/user:/usr/bin/bash
2 Likes

Change default shell from bash to zsh by default? - Development - Whonix Forum

Default Interactive Shell

2 Likes

Thank you @adrelanos.

usermod or chsh - it still doesn’t work consistently though.

STR:

  1. Create an AppVM (a DVM template) based on whonix-workstation-17 template.
  2. In /rw/config/rc.local set:
chsh --shell bash $(id -un 1000)
  1. Shutdown the AppVM
  2. Start the AppVM.

Result:

$ printenv | grep -i shell
SHELL=bash
  1. Start a disposable based on that same AppVM (being a DVM template).

Result:

[workstation user ~]% printenv | grep -i shell
SHELL=/usr/bin/zsh
SHELL=/usr/bin/zsh
[workstation user ~]% grep user /etc/passwd
user:x:1000:1000::/home/user:/usr/bin/zsh
[workstation user ~]% cat /rw/config/rc.local 
#!/bin/sh

chsh --shell bash $(id -un 1000)

For root (id 0), in both scenarios the shell is correctly set.

IOW, in disposables, it seems the command has no effect.

Why is that?

1 Like

Same issue would probably also happen when using that method to attempt to change from a Qubes Debian Template from its default bash shell to any other shell. This is likely unspecific to Whonix.

The reason is probably that /rw/config/rc.local runs too late after the Linux user account has already been logged in.

/rw/config/rc.local-early.d/*.rc , /rw/config/rc.local-early as documented on Config files | Qubes OS might work better.

1 Like

Same issue would probably also happen when using that method to attempt to change from a Qubes Debian Template from its default bash shell to any other shell. This is likely unspecific to Whonix.

Actually, it seems Whonix-specific. I tried the same using a Debian template, just switching the shell from the default bash to zsh in the exact same way through /rw/config/rc.local and it works as expected - in AppVM and in DispVM the shell is switched successfully for both root and user.

The reason is probably that /rw/config/rc.local runs too late after the Linux user account has already been logged in.

No, that is not the case because there is no login before rc.local completes. Even if the Whonix-based disposable is explicitly started without explicitly running any apps in it, then starting a terminal in it, the result is:

  • for root: shell is switched successfully in AppVM and DispVM
  • for user: shell is switched successfully only in AppVM

What do you think?

1 Like

Potentially due to different systemd unit files. These can lead to different race conditions.

Since other mechanisms are available,

  • change in Template as documented
  • Qubes rc.local-early
  • systemd unit files

I won’t be investigating this corner case. Consider this unsupported. Tested source code patches might be acceptable. (Contributions)

1 Like

Potentially due to different systemd unit files. These can lead to different race conditions.

/usr/lib/qubes/init/setup-rw.sh
/usr/lib/systemd/system/qubes-mount-dirs.service

are identical in Whonix and Debian templates.

Since other mechanisms are available,

  • change in Template as documented
  • Qubes rc.local-early
  • systemd unit files

I know but:

AFAIK, #2 is not available in Qubes 4.2.4, so I can’t test.
#1 and #3 involve template modification, so they rather seem different use cases.

I won’t be investigating this corner case.

As it seems, this is a bug. I can’t investigate further as well.

Thanks.

@murdock

Thank you for your responses too!

3 Likes

Related but different systemd unit files - unrelated ones - can lead to different race conditions.

You can have a systemd units that only does work based on conditions. Either using systemd configuration and/or shell scripting. A condition could be “only inside App Qube”, “only inside App Qubes with name custom-vm-name” or “only inside Disposable”.

1 Like

Related but different systemd unit files - unrelated ones - can lead to different race conditions.

I can’t understand which particular files you are talking about.

You can have a systemd units that only does work based on conditions.

Sure but that still involves template modification.

1 Like
systemctl list-units

All inside folder /usr/lib/systemd/system and other related systemd configuration folders.

Why are these related? Because systemd builds a dependency chain. Races can have different results depending on installed systemd units and system performance. A race might indicate a bug. Races can be fixed with correct systemd unit files properly declaring dependencies

(Qubes rc.local evidently does not run before for user login.)

(The introduction of rc.local-early by Qubes could be considered a bugfix for rc.local vs user login races.)

But Template modification is OK?

Other option not requiring Template modifications:

2 Likes

I understand systemd units run in a complicated (non-sequential) way. I just wonder which ones Whonix modifies (making them different from those in Debian).

Can you tell me which those are?

But Template modification is OK?

Sure. Just a different use case.

Other option not requiring Template modifications:

I will check these options too. A) looks interesting.

1 Like

Can be found out.

myfind recommended. Documented here:

Find Files

To search for systemd unit files:

myfind . | grep --fixed-strings "systemd" | grep --invert-match --fixed-strings ".conf"

To search for systemd drop-ins:

myfind . | grep --fixed-strings systemd | grep --fixed-strings service.d
1 Like
user@host:/tmp/download/derivative-maker > git describe 
17.4.0.3-developers-only
user@host:/tmp/download/derivative-maker > myfind . | grep --fixed-strings "systemd" | grep --invert-match --fixed-strings ".conf"
+ find . -type f -not -iwholename '*.git*'
user@host:/tmp/download/derivative-maker > myfind . | grep --fixed-strings systemd | grep --fixed-strings service.d
+ find . -type f -not -iwholename '*.git*'
1 Like