Hiding /etc/shadow from Debian psql wrapper
In the recent note titled "Hiding /etc/shadow from psql", I've
mentioned how calling psql
was causing auditd
to log denied reads of
/etc/shadow
and have showed one way to deal with this. Here is the continuation of this story, as thanks to insights from @hillu.bsky.social, it's clear that I've missed an important detail.
On Debian /usr/bin/psql
is actually a distro specific wrapper over
the actual psql
binary. I missed that previously:
$ ls -l /usr/bin/psql
lrwxrwxrwx 1 root root 37 Mar 14 2023 /usr/bin/psql -> ../share/postgresql-common/pg_wrapper
This is part of Debian's mechanism for managing multiple PostgreSQL clusters and versions. So the behavior I've observed earlier is Debian specific.
And as @hillu pointed out, /etc/shadow
read is ultimately triggered by getpwuid
Perl builtin. Which is called by /usr/share/perl5/PgCommon.pm
, called from
/usr/share/postgresql-common/pg_wrapper
by invoking user_cluster_map()
. If I understood correctly, the
actual read of /etc/shadow
is not needed and is only a side effect of triggering
getpwuid
.
Anyway, the following line of the postgresql-common/pg_wrapper
suggests one way to avoid
this excessive read attempt:
($version, $cluster, $db) = user_cluster_map() unless ($cluster or $explicit_host or $explicit_port);
Passing explicit connection info to psql
will stop the wrapper
from entering the code path that ends on shadow file read. But the form of such
call is not arbitrary - in the original scenario
connection params were in fact passed, but using --dbname CONNSTRING
. And Debian wrapper
is not trying to extract anything from that. But it does understand
psql -h
.
And even without resigning from using --dbname CONNSTRING
form, we can still
escape the issue by adding extra explicit -h HOST
. In fact, turns out HOST
can be anything then, because as psql
docs state, "--dbname [...] can be a connection string. If so, connection string parameters will override any conflicting command line options". At the same time our Perl wrapper
will be happy not to call user_cluster_map
and leave /etc/shadow
alone:
psql --dbname CONNSTRING -h dummy
But that's little hacky. Ideally, PgCommon.pm
would not be using getpwuid
at all.