Security¶
This page tries to provide some background information for security conscious-users
and interested readers.
On a high-level isd
is nothing more than a fancy TUI/wrapper around
systemctl
. I hope this explains everything. Thanks! See you around!
Wait, you want more details? Wow... I never thought that anybody really wanted to know. So let's get lost in details 🔬!
Shell Injection¶
As mentioned above, isd
wraps around systemctl
calls.
systemctl
is executed as a sub-process via the Python
subprocess module.
In this context, the important question is whether or not
shell injection attacks are possible.
isd
relies on the implementation of Python subprocess
to correctly escape arguments and to prevent shell injection attacks.
If you would like to learn more about, I would recommend reading the
Security Considerations
section from the subprocess documentation.
The important part is that isd
always uses shell=False
and let's the battle-tested
Python standard library take care of the scary part.
For completeness, isd
also calls asyncio.create_subprocess_exec
to create and interact with Python Process
instances in an asynchronous fashion, but internally, the same escaping is handled by the
Python standard library.
Though, what actually happens in the background is always something to scrutinize.
Trust¶
At the end of the day, it is your call which software you trust.
The source of isd
is publicly available to increase your trust into the application.
Not only that but the software is build via a fully reproducible pipeline
with nix!
This means that nobody has to use/trust the build artifacts but everybody can
build their own artifact via nix build
and create an identical version.
But even if you trust isd
1, it does not mean that there are no risks
this library introduces or that it cannot further improve!
Privileged Execution (sudo
)¶
In general, it is a good idea to never run commands/binaries with elevated privileges.
isd
is designed in such a way that you never have to run it with sudo
.
isd
is able to automatically prefix the systemctl
subprocess calls with sudo
if necessary and may ask you for your password via
the normal terminal password prompt.
But note that isd
can also take advantage of polkit
and does not
have to rely on sudo
to interact with system
units2.
See the polkit
settings page to see how to configure polkit
to let an unprivileged user manage specific system
units.
The only exception is the systemctl edit
command.
Issues with systemctl edit
¶
Opinionated Section
The following section contains my personal opinion
about design decisions regarding systemctl edit
.
Nothing more and nothing less. I am still a big fan
of systemd. Otherwise, why would I have spend sooo much time
creating a TUI for it?
IMHO, systemctl edit
is a bit of an odd 🦆 as it is orthogonal to
other systemctl
commands.
To cite the systemctl
man page:
systemctl - Control the systemd system and service manager
Now, is systemctl edit
something that controls a service manager?
If you ask me, no! systemctl edit
does much more/too much.
Before diving into the well-meant criticism,
let's start by highlighting the positive ☀️.
I am a big fan of systemctl edit
3 and think that it is one of the most
useful utilities when working with systemd
.
It makes it a lot easier to debug and improve the security of units.
And if it would have been called systemd-edit-unit
or something similar,
I would have almost no4 complaints.
However, isd
is primarily a wrapper around systemctl
and systemctl edit
is just an odd 🦆.
To better understand why, here is a snippet from the systemctl edit
man page:
Edit or replace a drop-in snippet or the main unit file, to extend or override the definition of the specified unit. [...] The editor [...] is invoked on temporary files which will be written to the real location if the editor exits successfully. After the editing is finished, configuration is reloaded [...].
So in essence, systemctl edit
creates a temporary file, opens an editor,
creates/writes a unit/drop-in file, and reloads the configuration.
My main issue is that by creating a drop-in file of a system
unit,
the systemctl edit
command always has to run with elevated privileges, often
by prefixing it with sudo
.
Otherwise, the command does not have the necessary privileges to create the
drop-in file. This behavior is also correct and important! No unprivileged users should
be able to edit the drop-in files of system
units.
But this means that systemctl edit
cannot rely on polkit
rules to allow
unprivileged users to manage subsets of system
units.
Although all other systemctl
sub-commands can.
As a result, isd
will always have a special case for systemctl edit
,
since it has to switch back to prefixing commands with sudo
even if
everything else could be managed with polkit
.
Also, it takes control over the terminal and starts the editor on its own as root.
And this is where I disagree with the current implementation.
Opening any editor as root
is, IMHO, not a good idea.
One annoyance is that many have user-specific configurations/plugins
that are not available if it is running as a different user.
The bigger issue is that I do not think we should trust all editors (especially
with large plugin ecosystems) to run with elevated privileges.
See, for example, the blog titled Can You Trust Your VSCode Extensions?.
You may disagree with this opinion but the interesting thing
is that (as far as I understand it), the systemd
folks have come
to a similar conclusion for pagers.
For example, if you run sudo PAGER=<custom-pager> systemctl show <service-with-long-output>
where PAGER != less
(for example, let the pager be moar) you will, see that it
will not open the provided pager.
You must explicitly enable it via sudo SYSTEMD_PAGERSECURE=1 PAGER=<custom-pager> systemctl show <service-with-long-output>
.
For details, see the SYSTEMD_PAGERSECURE
discussion. So I wonder if editor should be more trustworthy than pagers?
With this, I hope that I was able to communicate why I believe that systemctl edit
is an odd 🦆.
Aside Note
If you made it this far into the document, you need to know that you are an absolute 🦸.
And I hope that you are not scared to use your editor. And if you are, I bet it is not as scary as the reproductive organs of a 🦆.
systemctl edit --stdin
¶
For those that are closely following the release notes of systemd
,
you may already be aware of systemctl edit --stdin
:
--stdin: When used with edit, the contents of the file will be read from standard input and the editor will not be launched. In this mode, the old contents of the file are completely replaced. This is useful to "edit" unit files from scripts:
This already avoids opening an editor with elevated privileges and brings all
the other niceties of systemctl edit
into a single command.
In a future version of isd
, I plan on intercepting systemctl edit
commands,
to open editors as the current user and then only use elevated privileges for
the other steps.
Pagers¶
A pager is a program to display (not edit!) text on the terminal, in a user friendly way5.
By default systemd
will avoid running arbitrary pagers for system
units.
To quote the man pages from SYSTEMD_PAGERSECURE
:
When true, the "secure" mode of the pager is enabled; if false, disabled. If $SYSTEMD_PAGERSECURE is not set at all, secure mode is enabled if the effective UID is not the same as the owner of the login session. [...] In secure mode,
LESSSECURE=1
will be set when invoking the pager, and the pager shall disable commands that open or create new files or start new subprocesses. WhenSYSTEMD_PAGERSECURE
is not set at all, pagers which are not known to implement secure mode will not be used. (Currently onlyless(1)
implements secure mode.)
Effectively meaning that by default less
will be used as a pager for system
units.
Although this might be an annoyance, the documentation expands on the motivation (emphasize mine):
Note: when commands are invoked with elevated privileges, for example under
sudo
orpkexec
, care must be taken to ensure that unintended interactive features are not enabled. [...] SettingSYSTEMD_PAGERSECURE=0
or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note that if theSYSTEMD_PAGER
orPAGER
variables are to be honoured,SYSTEMD_PAGERSECURE
must be set too.
Neat! So systemd
tries to protect us from running untrusted pagers with elevated privileges and/or
accidentally running commands/sub-processes with elevated privileges from within the pager.
Something that they do not honour for EDITOR
, see Issues with systemctl edit
for more details on this subject.
Okay, but how does isd
work with pagers?
Currently, isd
takes a rather simple approach for the pagers.
It simply uses the pager that is configured via the settings or uses the pager from the environment variables
SYSTEMD_PAGER
or PAGER
. In all instances, isd
ignores the value of SYSTEMD_PAGERSECURE
!
The simple reason why this is not an issue is that isd
does not run the pager with elevated privileges.
Even if isd
may prefix the systemctl
call with sudo
, the result (or text) is read from the standard output6
and then fed to a pager as a new sub-process. This pager process runs without elevated privileges and as such
does not require more trust than any other program. :)
-
And if you do, thank you ↩
-
Where
systemctl edit
is an exception. See Issues withsystemctl edit
for more details. ↩ -
And especially
systemctl edit --runtime
! ↩ -
With the exception of how
systemctl edit
trusts$EDITOR
. ↩ -
Some initial data may be dropped while reading to improve the interactive features and avoid high memory usage. ↩