Hi Derek,

A few interesting things arise from this bug report.

>  pam_wtmpdb(su:session): add_entry: Adding an entry did not return 
> SQLITE_DONE: 8
>  pam_lastlog2(su:session): Delete statement did not return SQLITE_DONE: 8

1. forky will benefit from upstream's improved error reporting, which
shows the exact reason for the failure:

Jul 28 22:10:14 [su] pam_wtmpdb(su:session): Adding an entry failed: attempt to 
write a readonly database

2. This points within /usr/lib/systemd/system/locate.service to:

  ProtectSystem=strict

I reproduced this condition absent systemd by running:

  unshare --mount
  mount -o ro /var/log /var/log
  /etc/cron.daily/locate systemd-timer

> Running /etc/cron.daily/locate directly doesn't create the errors so it's
> something to do with the sandbox that systemd is setting up.

As you surmise, this is the service hardening tail wagging the
pre-existing functionality dog, in this case not letting a pam module
write to its log files.

One could play whack-a-mole here and open a hole with ReadWritePaths, or
demote ProtectSystem to "=full".

However, I think we can do better.

3. The real worker, /usr/bin/updatedb.findutils, uses 'su' to become
'nobody'. This is not the right way to drop privileges. su is designed
for human users, for a start. util-linux ships with 'runuser' which is
more suitable for system scripts, has a minimal pam configuration and
does not reproduce this problem! I tried this and it works, although it
would need to be considered carefully by the 'locate' maintainers for
unintended consequences.

I suggest this is fixed via a shell function which falls back to 'su' so
that 'locate' can still run on hurd (where there is no systemd anyway).

4. Arguably 'su' shouldn't really be logging to wtmpdb (it doesn't log
to wtmp). Unfortunately there doesn't seem to be sufficient expressivity
in the pam system to exclude one particular module while executing the
rest from '@include common=account'.

However, wtmpdb thought of this and allow one to exclude a service in
the wtmpdb pam config itself. This is done for ssh so that ssh's richer
libwtmpdb integration can be used instead. There is therefore this
workaround possible in /etc/pam.d/common-session:

  session       optional        pam_wtmpdb.so skip_if=sshd,su

This wouldn't fix the 'pam_lastlog2' case but the other resolutions
would.

So, we have three possible user workarounds:

  a) update /etc/pam.d/common.session
  b) copy the unit to /etc/systemd/system/locate.service and create
     a ReadWritePaths hole for /var/log/
  c) copy the unit to /etc/systemd/system/locate.service and change to
     ProtectSystem=full

one bugfix for the locate package:

  d) switch 'su' to 'runas' where available.

and one possible improvement to libpam-wtmpdb:

  e) add 'su' to the skip_if clause in pam config.

I think 'locate' is probably the most accurate home for this bug!

And well done for uncovering the mystery of why I get this in my wtmpdb
every night!

nobody                                 Tue Jun 23 07:35 - 07:38  (00:02)
nobody                                 Tue Jun 23 07:35 - 07:35  (00:00)
nobody                                 Tue Jun 23 07:35 - 07:35  (00:00)

Andrew

Reply via email to