In almost all circumstances, running Postgres as the root user creates an unnecessary potential security vulnerability should Postgres itself have a vulnerability.
The following question states that you cannot run Postgres as the root user without modifying the source code:
How can I run postgres under root user? but ends there.
I am looking to run Postgres in a Gramine shielded container. This is so it can interface with other Gramine shielded containers, which run on Intel SGX. The rest of our stack runs in Gramine using Gramine-specific tooling for SGX attestations. Some of this stack runs third-party code. Using some other Intel SGX-capable database is therefore not an option unless that database implements those Gramine-specific SGX attestation wrappers.
Gramine Shielded Containers (GSC) enforce that the user is root. Gramine mocks and reimplements various system calls and running whoami
and su
commands in a bash script running inside Gramine, I can see that user ‘root’ lacks the root permissions.
I therefore either need to modify GSC to run non-root executables inside Intel SGX, or I need to modify Postgres to run as root. I think the latter sounds more feasible. The former may even require forking a Linux OS to perform various SGX system calls without root privileges.
I have attempted the following:
<code>git clone https://github.com/postgres/postgres.git --branch REL_15_STABLE
sed -i '/exit(1);/ s/^////' src/backend/main/main.c
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "geteuid()" {} ; -exec sed -i 's/geteuid()/geteuid()/g' {} ;
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "getuid()" {} ; -exec sed -i 's/getuid()/getuid()/g' {} ;
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "stat_buf.st_uid" {} ; -exec sed -i 's/stat_buf.st_uid/stat_buf.st_uid/g' {} ;
sed -i 's/bool[[:space:]]*do_check_root[[:space:]]*=[[:space:]]*true;/bool do_check_root = false;/g' src/backend/main/main.c
<code>git clone https://github.com/postgres/postgres.git --branch REL_15_STABLE
cd postgres
sed -i '/exit(1);/ s/^////' src/backend/main/main.c
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "geteuid()" {} ; -exec sed -i 's/geteuid()/geteuid()/g' {} ;
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "getuid()" {} ; -exec sed -i 's/getuid()/getuid()/g' {} ;
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "stat_buf.st_uid" {} ; -exec sed -i 's/stat_buf.st_uid/stat_buf.st_uid/g' {} ;
sed -i 's/bool[[:space:]]*do_check_root[[:space:]]*=[[:space:]]*true;/bool do_check_root = false;/g' src/backend/main/main.c
</code>
git clone https://github.com/postgres/postgres.git --branch REL_15_STABLE
cd postgres
sed -i '/exit(1);/ s/^////' src/backend/main/main.c
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "geteuid()" {} ; -exec sed -i 's/geteuid()/geteuid()/g' {} ;
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "getuid()" {} ; -exec sed -i 's/getuid()/getuid()/g' {} ;
find . -type f ( -name "*.c" -o -name "*.h" ) -exec grep -l "stat_buf.st_uid" {} ; -exec sed -i 's/stat_buf.st_uid/stat_buf.st_uid/g' {} ;
sed -i 's/bool[[:space:]]*do_check_root[[:space:]]*=[[:space:]]*true;/bool do_check_root = false;/g' src/backend/main/main.c
But then the following command:
<code>initdb -D /usr/local/pgsql/data
<code>initdb -D /usr/local/pgsql/data
</code>
initdb -D /usr/local/pgsql/data
gives the following error:
<code> > [postgres 16/20] RUN /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data:
0.291 The files belonging to this database system will be owned by user "daemon".
0.291 This user must also own the server process.
0.291 The database cluster will be initialized with locale "C".
0.291 The default database encoding has accordingly been set to "SQL_ASCII".
0.291 The default text search configuration will be set to "english".
0.291 Data page checksums are disabled.
0.291 fixing permissions on existing directory /usr/local/pgsql/data ... ok
0.291 creating subdirectories ... ok
0.292 selecting dynamic shared memory implementation ... posix
0.292 selecting default max_connections ... 20
0.300 selecting default shared_buffers ... 400kB
0.330 selecting default time zone ... Etc/UTC
0.330 creating configuration files ... ok
0.330 running bootstrap script ... 2024-06-08 17:20:14.080 UTC [59] FATAL: data directory "/usr/local/pgsql/data" has wrong ownership
0.335 2024-06-08 17:20:14.080 UTC [59] HINT: The server must be started by the user that owns the data directory.
0.339 child process exited with exit code 1
0.339 initdb: removing contents of data directory "/usr/local/pgsql/data"
<code> > [postgres 16/20] RUN /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data:
0.291 The files belonging to this database system will be owned by user "daemon".
0.291 This user must also own the server process.
0.291
0.291 The database cluster will be initialized with locale "C".
0.291 The default database encoding has accordingly been set to "SQL_ASCII".
0.291 The default text search configuration will be set to "english".
0.291
0.291 Data page checksums are disabled.
0.291
0.291 fixing permissions on existing directory /usr/local/pgsql/data ... ok
0.291 creating subdirectories ... ok
0.292 selecting dynamic shared memory implementation ... posix
0.292 selecting default max_connections ... 20
0.300 selecting default shared_buffers ... 400kB
0.330 selecting default time zone ... Etc/UTC
0.330 creating configuration files ... ok
0.330 running bootstrap script ... 2024-06-08 17:20:14.080 UTC [59] FATAL: data directory "/usr/local/pgsql/data" has wrong ownership
0.335 2024-06-08 17:20:14.080 UTC [59] HINT: The server must be started by the user that owns the data directory.
0.339 child process exited with exit code 1
0.339 initdb: removing contents of data directory "/usr/local/pgsql/data"
</code>
> [postgres 16/20] RUN /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data:
0.291 The files belonging to this database system will be owned by user "daemon".
0.291 This user must also own the server process.
0.291
0.291 The database cluster will be initialized with locale "C".
0.291 The default database encoding has accordingly been set to "SQL_ASCII".
0.291 The default text search configuration will be set to "english".
0.291
0.291 Data page checksums are disabled.
0.291
0.291 fixing permissions on existing directory /usr/local/pgsql/data ... ok
0.291 creating subdirectories ... ok
0.292 selecting dynamic shared memory implementation ... posix
0.292 selecting default max_connections ... 20
0.300 selecting default shared_buffers ... 400kB
0.330 selecting default time zone ... Etc/UTC
0.330 creating configuration files ... ok
0.330 running bootstrap script ... 2024-06-08 17:20:14.080 UTC [59] FATAL: data directory "/usr/local/pgsql/data" has wrong ownership
0.335 2024-06-08 17:20:14.080 UTC [59] HINT: The server must be started by the user that owns the data directory.
0.339 child process exited with exit code 1
0.339 initdb: removing contents of data directory "/usr/local/pgsql/data"
I can modify this so that initdb runs from user ‘postgres’ which gives the error:
<code>> [postgres 18/22] RUN /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data:
0.208 initdb: could not look up effective user ID 1001: user does not exist
<code>> [postgres 18/22] RUN /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data:
0.208 initdb: could not look up effective user ID 1001: user does not exist
</code>
> [postgres 18/22] RUN /usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data:
0.208 initdb: could not look up effective user ID 1001: user does not exist
Using LD_PRELOAD
for geteuid()
is another angle of attack but my belief is that this is equivalent to the sed
commands above.