From 4703d041168ab6448971f1e1a5c9fd39169015bc Mon Sep 17 00:00:00 2001 From: Jelte Fennema-Nio Date: Fri, 5 Jan 2024 14:45:04 +0100 Subject: [PATCH v4 4/7] Prepare server code for addition of protocol extensions This commit adds a new GUC flag that should be set on protocol extensions parameters: GUC_PROTOCOL_EXTENSION. GUCs with this flag can only be configured by being part of the StartupMessage (i.e. PGC_S_CLIENT). The reason they are not allowed to be set at the server configuration is because these parameters control protocol behaviour, and such changes should be purely opt-in by a client. Otherwise it's very likely that clients will break that don't support this protocol feature. The reason these parameters are not allowed to be changed using regular SET/SET LOCAL commands is because otherwise the behaviour of the protocol might by changed by someone with only SQL access without the client realizing. Even a client/pooler that parses queries and detects SET commands is unable to detect all GUC changes, since a function call might change GUCs internally. --- src/backend/postmaster/postmaster.c | 8 ++++---- src/backend/utils/misc/guc.c | 13 +++++++++++-- src/include/utils/guc.h | 3 +++ src/include/utils/guc_tables.h | 1 + 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index feb471dd1df..0c14b830c30 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -124,6 +124,7 @@ #include "tcop/tcopprot.h" #include "utils/builtins.h" #include "utils/datetime.h" +#include "utils/guc_tables.h" #include "utils/memutils.h" #include "utils/pidfile.h" #include "utils/ps_status.h" @@ -2210,12 +2211,11 @@ retry1: valptr), errhint("Valid values are: \"false\", 0, \"true\", 1, \"database\"."))); } - else if (strncmp(nameptr, "_pq_.", 5) == 0) + else if (strncmp(nameptr, "_pq_.", 5) == 0 && !find_option(nameptr, false, true, ERROR)) { /* - * Any option beginning with _pq_. is reserved for use as a - * protocol-level option, but at present no such options are - * defined. + * We report unkown protocol extensions using the + * NegotiateProtocolVersion message instead of erroring */ unrecognized_protocol_options = lappend(unrecognized_protocol_options, pstrdup(nameptr)); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 8f65ef3d896..5998e9d656a 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -2011,7 +2011,7 @@ ResetAllOptions(void) gconf->context != PGC_USERSET) continue; /* Don't reset if special exclusion from RESET ALL */ - if (gconf->flags & GUC_NO_RESET_ALL) + if (gconf->flags & (GUC_NO_RESET_ALL | GUC_PROTOCOL_EXTENSION)) continue; /* No need to reset if wasn't SET */ if (gconf->source <= PGC_S_OVERRIDE) @@ -3573,6 +3573,14 @@ set_config_with_handle(const char *name, config_handle *handle, break; } + if (record->flags & GUC_PROTOCOL_EXTENSION && source != PGC_S_CLIENT) + { + ereport(elevel, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("parameter can only be set at the protocol level \"%s\"", name))); + return 0; + } + /* * Disallow changing GUC_NOT_WHILE_SEC_REST values if we are inside a * security restriction context. We can reject this regardless of the GUC @@ -4606,7 +4614,8 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt) */ if ((record->context == PGC_INTERNAL) || (record->flags & GUC_DISALLOW_IN_FILE) || - (record->flags & GUC_DISALLOW_IN_AUTO_FILE)) + (record->flags & GUC_DISALLOW_IN_AUTO_FILE) || + (record->flags & GUC_PROTOCOL_EXTENSION)) ereport(ERROR, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), errmsg("parameter \"%s\" cannot be changed", diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 471d53da8f0..9890d09b3c8 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -223,6 +223,9 @@ typedef enum #define GUC_DISALLOW_IN_AUTO_FILE \ 0x002000 /* can't set in PG_AUTOCONF_FILENAME */ #define GUC_RUNTIME_COMPUTED 0x004000 /* delay processing in 'postgres -C' */ +#define GUC_PROTOCOL_EXTENSION \ + 0x008000 /* only allowed to be set using + * ParameterSet and StartupMessage */ #define GUC_UNIT_KB 0x01000000 /* value is in kilobytes */ #define GUC_UNIT_BLOCKS 0x02000000 /* value is in blocks */ diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index 0a2e274ebb2..4bba3dc3ccd 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -99,6 +99,7 @@ enum config_group PRESET_OPTIONS, CUSTOM_OPTIONS, DEVELOPER_OPTIONS, + PROTOCOL_EXTENSION, }; /* -- 2.34.1