Re: Introduce psystem() to replace system()

From: Haibo Yan <tristan(dot)yim(at)gmail(dot)com>
To: "Jonathan Gonzalez V(dot)" <jonathan(at)abdiel(dot)eu>
Cc: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: Introduce psystem() to replace system()
Date: 2026-08-11 01:11:33
Message-ID: CABXr29GzFpfJjZip1ApuPLGQVF_PXY2Za0qo6SvM+Ppf658q2A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Mon, Aug 10, 2026 at 12:28 PM Jonathan Gonzalez V. <jonathan(at)abdiel(dot)eu>
wrote:

>
> Hello!!
>
> For some time I've been wondering why PostgreSQL needs system() calls,
> which use a shell that can lead to many problems, and also why it
> requires a shell to run a command.
>
> I first started thinking about this when I was trying to run a full
> distroless PostgreSQL container. It turns out that isn't possible since
> the shell is a requirement, and distroless containers are secure exactly
> _because_ there's no shell to execute any command other than the ones
> that are meant to be executed.
>
> After some research I found out that using system() has other problems,
> like issues related to quoting that are really painful to solve [0][1],
> and also the exit codes control[2]. Both topics have already been
> discussed on the list.
>
> But the main argument now for me is security. Not having a shell avoids
> any possible PATH injection, missing quoting to escape a command, or new
> lines that the shell interprets differently from what you'd expect.
>
> After some thinking I came up with a small interface, which only purpose
> is to replace system() calls in a more smooth way using execv() under
> the hood. I suppose you could use execl() but I've decided to keep it
> simple, leaving the opportunity to expand in the future. I already
> implemented one call with `pg_ctl initdb` as an example.
>
> There's an important topic related to using shell versus not a shell. In
> some places like `archive_command` people may use `&&`, but this idea
> aims to avoid this kind of behavior since it's not secure. Probably we
> can implement a way to run commands in sequence, or simply tell the
> users that this isn't allowed anymore, but it's possible to trigger
> commands in sequence since the interface allows to manipulate the STDIN
> and STDOUT.
>
> I would like to open the discussion here if this is the right direction.
> There's a lot to do and this still a work in progress, the current patch
> is small and simple, but already provides building blocks in this
> direction.
>
> Hi Jonathan

Thanks for working on this. I think avoiding the shell for cases where
PostgreSQL is just
invoking a known executable makes sense.

There is some related work here which may be worth looking at:

https://www.postgresql.org/message-id/flat/CAGECzQQh6VSy3KG4pN1d%3Dh9J%3DD1rStFCMR%2Bt7yh_Kwj-g87aLQ%40mail.gmail.com

That effort ran into some similar issues around replacing system()/popen()
and handling the
fork/exec boundary.

A few things I noticed in this patch:

1. system() and execv() do not have the same semantics. For internal
commands such as pg_ctl
invoking initdb, that is probably fine and preferable. But for things like
archive_command,
shell features such as PATH lookup, &&, pipes and redirection are part of
the existing
interface, so changing those would be a compatibility decision rather than
just an
implementation change.
2. For pipelines, pcommand_exec() only knows the stdin/stdout/stderr FDs.
After fork(),
however, a child may inherit other pipe endpoints as well. Those need to be
closed before
exec(), otherwise an unused write end can keep a pipe alive and prevent EOF
from being seen.
3. I also wonder about returning errno from pcommand_exec(). An execv()
failure should
probably remain distinguishable from a program that successfully execs and
later exits with
the same numeric status. An error pipe from child to parent may be useful
here.

Overall I like the direction, but I think it would be useful to reuse some
of the lessons
from the earlier pg_system() / pg_popen() work before this grows into a
more general process
/pipeline API.

Regards,
Haibo

> [0] https://www.postgresql.org/message-id/7606.1153326421%40sss.pgh.pa.us
> [1]
> https://www.postgresql.org/message-id/CA%2BTgmobBmWWCgPUd04NGoQ%3D_XvcidV%2BsE2F7KChEXfs8KBPg6w%40mail.gmail.com
> [2] https://www.postgresql.org/message-id/21292.1358698487%40sss.pgh.pa.us
>
> --
> Jonathan Gonzalez V.
> EDB https://enterprisedb.com
>

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Bharath Rupireddy 2026-08-11 01:25:00 Re: Introduce XID age based replication slot invalidation
Previous Message Tom Lane 2026-08-11 00:56:22 Re: plpython tests fail against python 3.14 under Valgrind