Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c32416e

Browse files
committed
Code review for various recent GUC hacking. Don't elog(ERROR) when
not supposed to (fixes problem with postmaster aborting due to mistaken postgresql.conf change); don't call superuser() when not inside a transaction (fixes coredump when, eg, try to set log_statement from PGOPTIONS); some message style guidelines enforcement.
1 parent 617d6ea commit c32416e

File tree

2 files changed

+137
-97
lines changed

2 files changed

+137
-97
lines changed

src/backend/commands/variable.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.102 2004/08/30 02:54:38 momjian Exp $
12+
* $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.103 2004/08/31 19:28:51 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -475,16 +475,23 @@ show_timezone(void)
475475
const char *
476476
assign_XactIsoLevel(const char *value, bool doit, GucSource source)
477477
{
478-
if (doit && source >= PGC_S_INTERACTIVE)
478+
if (SerializableSnapshot != NULL)
479479
{
480-
if (SerializableSnapshot != NULL)
480+
if (source >= PGC_S_INTERACTIVE)
481481
ereport(ERROR,
482482
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
483483
errmsg("SET TRANSACTION ISOLATION LEVEL must be called before any query")));
484-
if (IsSubTransaction())
484+
else
485+
return NULL;
486+
}
487+
if (IsSubTransaction())
488+
{
489+
if (source >= PGC_S_INTERACTIVE)
485490
ereport(ERROR,
486491
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
487492
errmsg("SET TRANSACTION ISOLATION LEVEL must not be called in a subtransaction")));
493+
else
494+
return NULL;
488495
}
489496

490497
if (strcmp(value, "serializable") == 0)

src/backend/utils/misc/guc.c

Lines changed: 126 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Written by Peter Eisentraut <peter_e@gmx.net>.
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.236 2004/08/31 04:53:44 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.237 2004/08/31 19:28:51 tgl Exp $
1414
*
1515
*--------------------------------------------------------------------
1616
*/
@@ -1848,6 +1848,10 @@ static int guc_name_compare(const char *namea, const char *nameb);
18481848
static void push_old_value(struct config_generic * gconf);
18491849
static void ReportGUCOption(struct config_generic * record);
18501850
static char *_ShowOption(struct config_generic * record);
1851+
static bool check_userlimit_privilege(struct config_generic *record,
1852+
GucSource source, int elevel);
1853+
static bool check_userlimit_override(struct config_generic *record,
1854+
GucSource source);
18511855

18521856

18531857
/*
@@ -2034,7 +2038,7 @@ static bool
20342038
is_custom_class(const char *name, int dotPos)
20352039
{
20362040
/*
2037-
* The assign_custom_variable_classes has made sure no empty
2041+
* assign_custom_variable_classes() has made sure no empty
20382042
* identifiers or whitespace exists in the variable
20392043
*/
20402044
bool result = false;
@@ -3233,22 +3237,14 @@ set_config_option(const char *name, const char *value,
32333237
if (newval < conf->reset_val)
32343238
{
32353239
/* Limit non-superuser changes */
3236-
if (source > PGC_S_UNPRIVILEGED && !superuser())
3237-
{
3238-
ereport(elevel,
3239-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3240-
errmsg("permission denied to set parameter \"%s\"",
3241-
name),
3242-
errhint("must be superuser to change this value to false")));
3240+
if (!check_userlimit_privilege(record, source,
3241+
elevel))
32433242
return false;
3244-
}
32453243
}
32463244
if (newval > *conf->variable)
32473245
{
32483246
/* Allow change if admin should override */
3249-
if (source < PGC_S_UNPRIVILEGED &&
3250-
record->source > PGC_S_UNPRIVILEGED &&
3251-
!superuser())
3247+
if (check_userlimit_override(record, source))
32523248
changeVal = changeValOrig;
32533249
}
32543250
}
@@ -3338,30 +3334,25 @@ set_config_option(const char *name, const char *value,
33383334
}
33393335
if (record->context == PGC_USERLIMIT)
33403336
{
3341-
/* handle log_min_duration_statement, -1=disable */
3342-
if ((newval != -1 && conf->reset_val != -1 &&
3343-
newval > conf->reset_val) || /* increase duration */
3344-
(newval == -1 && conf->reset_val != -1)) /* turn off */
3337+
/*
3338+
* handle log_min_duration_statement: if it's enabled
3339+
* then either turning it off or increasing it
3340+
* requires privileges.
3341+
*/
3342+
if (conf->reset_val != -1 &&
3343+
(newval == -1 || newval > conf->reset_val))
33453344
{
33463345
/* Limit non-superuser changes */
3347-
if (source > PGC_S_UNPRIVILEGED && !superuser())
3348-
{
3349-
ereport(elevel,
3350-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3351-
errmsg("permission denied to set parameter \"%s\"",
3352-
name),
3353-
errhint("Must be superuser to increase this value or turn it off.")));
3346+
if (!check_userlimit_privilege(record, source,
3347+
elevel))
33543348
return false;
3355-
}
33563349
}
3357-
/* Allow change if admin should override */
3358-
if ((newval != -1 && *conf->variable != -1 &&
3359-
newval < *conf->variable) || /* decrease duration */
3360-
(newval != -1 && *conf->variable == -1)) /* turn on */
3350+
/* Admin override includes turning on or decreasing */
3351+
if (newval != -1 &&
3352+
(*conf->variable == -1 || newval < *conf->variable))
33613353
{
3362-
if (source < PGC_S_UNPRIVILEGED &&
3363-
record->source > PGC_S_UNPRIVILEGED &&
3364-
!superuser())
3354+
/* Allow change if admin should override */
3355+
if (check_userlimit_override(record, source))
33653356
changeVal = changeValOrig;
33663357
}
33673358
}
@@ -3450,23 +3441,21 @@ set_config_option(const char *name, const char *value,
34503441
return false;
34513442
}
34523443
if (record->context == PGC_USERLIMIT)
3453-
/* No REAL PGC_USERLIMIT */
34543444
{
3455-
/* Limit non-superuser changes */
3456-
if (source > PGC_S_UNPRIVILEGED && !superuser())
3445+
/* No REAL PGC_USERLIMIT at present */
3446+
if (newval < conf->reset_val)
34573447
{
3458-
ereport(elevel,
3459-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3460-
errmsg("permission denied to set parameter \"%s\"",
3461-
name),
3462-
errhint("Must be superuser to increase this value or turn it off.")));
3463-
return false;
3448+
/* Limit non-superuser changes */
3449+
if (!check_userlimit_privilege(record, source,
3450+
elevel))
3451+
return false;
3452+
}
3453+
if (newval > *conf->variable)
3454+
{
3455+
/* Allow change if admin should override */
3456+
if (check_userlimit_override(record, source))
3457+
changeVal = changeValOrig;
34643458
}
3465-
/* Allow change if admin should override */
3466-
if (source < PGC_S_UNPRIVILEGED &&
3467-
record->source > PGC_S_UNPRIVILEGED &&
3468-
!superuser())
3469-
changeVal = false;
34703459
}
34713460
}
34723461
else
@@ -3559,27 +3548,17 @@ set_config_option(const char *name, const char *value,
35593548
(*var_hook) (&var_value, *conf->variable, true,
35603549
source);
35613550

3562-
/* Limit non-superuser changes */
35633551
if (new_value > reset_value)
35643552
{
35653553
/* Limit non-superuser changes */
3566-
if (source > PGC_S_UNPRIVILEGED && !superuser())
3567-
{
3568-
ereport(elevel,
3569-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3570-
errmsg("permission denied to set parameter \"%s\"",
3571-
name),
3572-
errhint("Must be superuser to increase this value.")));
3554+
if (!check_userlimit_privilege(record, source,
3555+
elevel))
35733556
return false;
3574-
}
35753557
}
3576-
3577-
/* Allow change if admin should override */
35783558
if (new_value < var_value)
35793559
{
3580-
if (source < PGC_S_UNPRIVILEGED &&
3581-
record->source > PGC_S_UNPRIVILEGED &&
3582-
!superuser())
3560+
/* Allow change if admin should override */
3561+
if (check_userlimit_override(record, source))
35833562
changeVal = changeValOrig;
35843563
}
35853564
}
@@ -3702,6 +3681,71 @@ set_config_option(const char *name, const char *value,
37023681
return true;
37033682
}
37043683

3684+
/*
3685+
* Check whether we should allow a USERLIMIT parameter to be set
3686+
*
3687+
* This is invoked only when the desired new setting is "less" than the
3688+
* old and so appropriate privileges are needed. If the setting should
3689+
* be disallowed, either throw an error (in interactive case) or return false.
3690+
*/
3691+
static bool
3692+
check_userlimit_privilege(struct config_generic *record, GucSource source,
3693+
int elevel)
3694+
{
3695+
/* Allow if trusted source (e.g., config file) */
3696+
if (source < PGC_S_UNPRIVILEGED)
3697+
return true;
3698+
/*
3699+
* Allow if superuser. We can only check this inside a transaction,
3700+
* though, so assume not-superuser otherwise. (In practice this means
3701+
* that settings coming from PGOPTIONS will be treated as non-superuser)
3702+
*/
3703+
if (IsTransactionState() && superuser())
3704+
return true;
3705+
3706+
ereport(elevel,
3707+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3708+
errmsg("permission denied to set parameter \"%s\"",
3709+
record->name),
3710+
(record->vartype == PGC_BOOL) ?
3711+
errhint("Must be superuser to change this value to false.")
3712+
: ((record->vartype == PGC_INT) ?
3713+
errhint("Must be superuser to increase this value or turn it off.")
3714+
: errhint("Must be superuser to increase this value."))));
3715+
return false;
3716+
}
3717+
3718+
/*
3719+
* Check whether we should allow a USERLIMIT parameter to be overridden
3720+
*
3721+
* This is invoked when the desired new setting is "greater" than the
3722+
* old; if the old setting was unprivileged and the new one is privileged,
3723+
* we should apply it, even though the normal rule would be not to.
3724+
*/
3725+
static bool
3726+
check_userlimit_override(struct config_generic *record, GucSource source)
3727+
{
3728+
/* Unprivileged source never gets to override this way */
3729+
if (source > PGC_S_UNPRIVILEGED)
3730+
return false;
3731+
/* If existing setting is from privileged source, keep it */
3732+
if (record->source < PGC_S_UNPRIVILEGED)
3733+
return false;
3734+
/*
3735+
* If user is a superuser, he gets to keep his setting. We can't check
3736+
* this unless inside a transaction, though. XXX in practice that
3737+
* restriction means this code is essentially worthless, because the
3738+
* result will depend on whether we happen to be inside a transaction
3739+
* block when SIGHUP arrives. Dike out until we can think of something
3740+
* that actually works.
3741+
*/
3742+
#ifdef NOT_USED
3743+
if (IsTransactionState() && superuser())
3744+
return false;
3745+
#endif
3746+
/* Otherwise override */
3747+
return true;
3748+
}
37053749

37063750

37073751
/*
@@ -5450,22 +5494,19 @@ assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
54505494
* Syntax error due to token following space after token or
54515495
* non alpha numeric character
54525496
*/
5453-
pfree(buf.data);
5454-
ereport(WARNING,
5497+
ereport(LOG,
54555498
(errcode(ERRCODE_SYNTAX_ERROR),
5456-
errmsg("illegal syntax for custom_variable_classes \"%s\"", newval)));
5499+
errmsg("invalid syntax for custom_variable_classes: \"%s\"", newval)));
5500+
pfree(buf.data);
54575501
return NULL;
54585502
}
54595503
symLen++;
54605504
appendStringInfoChar(&buf, (char) c);
54615505
}
54625506

5507+
/* Remove stray ',' at end */
54635508
if (symLen == 0 && buf.len > 0)
5464-
5465-
/*
5466-
* Remove stray ',' at end
5467-
*/
5468-
buf.data[--buf.len] = 0;
5509+
buf.data[--buf.len] = '\0';
54695510

54705511
if (buf.len == 0)
54715512
newval = NULL;
@@ -5479,39 +5520,32 @@ assign_custom_variable_classes(const char *newval, bool doit, GucSource source)
54795520
static bool
54805521
assign_stage_log_stats(bool newval, bool doit, GucSource source)
54815522
{
5482-
if (newval)
5523+
if (newval && log_statement_stats)
54835524
{
5484-
if (log_statement_stats)
5485-
{
5486-
if (doit)
5487-
ereport(ERROR,
5488-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5489-
errmsg("cannot enable parameter when \"log_statement_stats\" is true.")));
5490-
else
5491-
return false;
5492-
}
5493-
return true;
5525+
if (source >= PGC_S_INTERACTIVE)
5526+
ereport(ERROR,
5527+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5528+
errmsg("cannot enable parameter when \"log_statement_stats\" is true")));
5529+
else
5530+
return false;
54945531
}
54955532
return true;
54965533
}
54975534

5498-
54995535
static bool
55005536
assign_log_stats(bool newval, bool doit, GucSource source)
55015537
{
5502-
if (newval)
5538+
if (newval &&
5539+
(log_parser_stats || log_planner_stats || log_executor_stats))
55035540
{
5504-
if (log_parser_stats || log_planner_stats || log_executor_stats)
5505-
{
5506-
if (doit)
5507-
ereport(ERROR,
5508-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5509-
errmsg("cannot enable \"log_statement_stats\" when \"log_parser_stats\",\n"
5510-
"\"log_planner_stats\", or \"log_executor_stats\" is true.")));
5511-
else
5512-
return false;
5513-
}
5514-
return true;
5541+
if (source >= PGC_S_INTERACTIVE)
5542+
ereport(ERROR,
5543+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5544+
errmsg("cannot enable \"log_statement_stats\" when "
5545+
"\"log_parser_stats\", \"log_planner_stats\", "
5546+
"or \"log_executor_stats\" is true")));
5547+
else
5548+
return false;
55155549
}
55165550
return true;
55175551
}
@@ -5534,7 +5568,6 @@ assign_transaction_read_only(bool newval, bool doit, GucSource source)
55345568
static const char *
55355569
assign_canonical_path(const char *newval, bool doit, GucSource source)
55365570
{
5537-
55385571
if (doit)
55395572
{
55405573
/* We have to create a new pointer to force the change */

0 commit comments

Comments
 (0)