On 9/23/25 11:29 PM, Lennart Poettering wrote:
On Di, 23.09.25 15:44, Ian Pilcher ([email protected]) wrote:
>
(The symlinks under /tmp/keys are needed, because stunnel doesn't
support any form of variable expansion in its configuration file.)

Uff, the /tmp/keys thing is an instant DoS, I hope you realize that?
That's not how security is done these days (or in fact has been done
for the last decade or two).

I was not aware of that.  Got a link to something that explains it?
(Note that I am using DynamicUser=true, so the tmp directory is
private.)

I'm also not sure what the alternative is.  I need to symlink or copy
the keys *somewhere*, so that they have fixed paths that can be
referenced from the stunnel config.

(I do know about envsubst, but that requires file redirection, which
means I have to call it from a shell, with all that implies for the
attack surface.  StandardInput= and StandardOutput= would work if they
could be set per-command, but that doesn't seem to be the case.)

Unfortunately, I quickly discovered that this doesn't work, because the
SELinux context of the keys is lost when they are copied into the
/run/credentials directory.

Yeah, the selinux policy can set new labels if it wants for that. Note
that the creds are not necessarily just copied, they are also
decrypted+authenticated. Moreover they are chowned/acled to the
service user. Or in other words, while they are generated from the
source files they really are their own thing – with their own
ownership/access mode/security identity – once they show up in
$CREDENIAL_DIRECTORY. Hence copying over the label is not an obvious
thing to do I'd say, because you might possibly give access to
security sensitive material (i.e. the plaintext creds) to a label that
shouldn't have that (i.e. a label intended for the encrypted
creds only, which are something that need little protection).

Makes sense.

So far there's an explicit relabel call when we create the dir that we
place the creds in; your selinux policy/database can hook into that to
label the creds according to your needs. We could also relabel the
cred files individually when we create them, but that'd require a
patch. At this point selinux stuff really requires community patches
to work nicely, because none of the systemd upstream developers use it
(at least to my knowledge).

That does seem like the ideal approach.  Unfortunately, it looks like
it requires some policy surgery, rather than just a file context rule
to make it work.

I added a file context rule:

/run/credentials/stunnel.service  directory  system_u:object_r:cert_t:s0

It worked, but now systemd can't copy the credentials into the
directory.

type=AVC msg=audit(1758722106.218:1109): avc:  denied  { add_name } for
  pid=2796 comm="(sd-mkdcreds)" name=".#cred3f2dbe5fd2f0f0cc"
  scontext=system_u:system_r:init_t:s0
  tcontext=system_u:object_r:cert_t:s0 tclass=dir permissive=0

Rather than relabeling the directory when it's created, it might be
better to wait until all of the credential files have been created, and
then perform a recursive relabel on the directory.  (This would have the
added benefit of allowing the system administrator to assign different
labels to different credentials if they needed to do that for some
reason.)

Then the relabel would need to be reversed before the credentials
directory can be deleted when the service is stopped.  Otherwise
systemd won't be allowed to delete the directory.

type=AVC msg=audit(1758722106.241:1112): avc:  denied  { rmdir } for
  pid=1 comm="systemd" name="stunnel.service" dev="tmpfs" ino=2482
  scontext=system_u:system_r:init_t:s0
  tcontext=system_u:object_r:cert_t:s0 tclass=dir permissive=0

In fact, this can affect private /tmp directories as well.  I use the
following pattern to run services written in Python in the correct
SELinux domain.  (If I were to use SELinuxContext= to do this, I would
need to give the domain permission to run anything labeled bin_t,
because that is the label on the Python interpreter.)

ExecStartPre=/usr/bin/cp /usr/bin/python3 /tmp/python.sac
ExecStartPre=/usr/bin/chcon --reference /usr/local/bin/sacd /tmp/python.sac
ExecStart=/tmp/python.sac /usr/local/bin/sacd

If systemd (init_t) doesn't have permission to delete whatever context
python.sac has, it will fail to delete the private /tmp when the service
stops.  This can be easily worked around by deleting any relabeled files
with ExecStartPost= lines, but it's easy to forget to do this.  Would it
be crazy for systemd to recursively relabel private /tmp directories
back to tmp_t before deleting them to ensure that the deletion succeeds?

None of this seems like it would be overly complicated, so I'd be
happy to try to create a PR to do this.  (I'd probably need a few
pointers on where in the code the relabels would need to be added/
moved.)

(I am also not strictly opposed to just copying the label over, but
that'd require a patch to be submitted, and someone from the selinux
upstream folks needs to OK that, but that might be hard to get)

As you mention above, it would probably need to be opt-in, since there
are times that it wouldn't be appropriate.  As a system administrator,
using file context rules (without needing to create policy modules)
feels like a good balance of flexibility and complexity.

--
========================================================================
If your user interface is intuitive in retrospect ... it isn't intuitive
========================================================================

Reply via email to