1) would it be enough to just disable WRITING to the filesystem (COPY
... TO ..., COPY TO ... PROGRAM ...) or are some reading functions
also potentially exploitable or at least making attackers life easier
?
I would protect read paths as well as write ones.
Though ISTM reading would need to be more fine-grained - raw filesystem reads and system reads (i.e., something like get_raw_page(...))
2) should configuration be all-or-nothing or more fine-tunable (maybe
a comma-separated list of allowed features) ?
First pass, all-or-nothing, focus on architecture and identification. Ideally we can then easily go in and figure out specific capabilities that need to be enumerated should we desire. Or, as noted below, figure out how to do a DBA administered whitelist.
3) should this be back-patched (we can provide batches for all
supported PgSQL versions)
I would love to in theory, but to do this right I suspect that the amount of desirable refactoring would make doing so prohibitive.
4) We should likely start with this flag off, but any paranoid (read -
good and security conscious) DBA can turn it on.
In the end the vast majority of our users will have the decision as to the default state of this decided for them by their distribution or service provider. I'm fine with having build-from-source users get the more permissive default.
5) Which file access functions should be in the unsafe list -
pg_current_logfile is likely safe as is pg_relation_filenode, but
pg_ls_dir likely is not. some subversions might be ok again, like
pg_ls_waldir ?
6) or should we control it via disabling the pg_*_server_* roles for
different take of configuration from 5) ?
I would suggest neither: we should funnel user-initiated access to the filesystem, for read and write, through its own API that will simply prevent all writes (and maybe reads) based upon this flag. If we can somehow enforce that a C coded extension also use this API we should do so, but IIUC that is not possible.
This basically puts things in a "default deny" mode. I do think that we need something that permits a filesystem user to then say "except these" (i.e., a whitelist). The thing added to the whitelist should be available in the PostgreSQL log file when the API rejects the attempt to access the filesystem. Unfortunately, at the moment I hit a brick wall when thinking exactly how that could be accomplished. At least, in a minimal/zero trust type of setup. Having the API access include the module, function, and version making the request and having a semantic versioning based whitelist (like, e.g., npm) would work sufficiently well in a "the only ones that get installed on the server are trusted to play by the rules" setup.
Probably over-engineering it like I have a tendency to do, but some food for thought nonetheless.
David J.