Improve handling of GUC USERLIMIT variables by reorganizing code. Also,

handle new postgresql.conf values with SIGHUP better by better enforcing
USERLIMIT settings on existing non-super-user backends.
This commit is contained in:
Bruce Momjian 2004-04-05 02:48:09 +00:00
parent 53ddde5b74
commit a12fc7dae6
1 changed files with 92 additions and 75 deletions

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.195 2004/04/01 21:28:45 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.196 2004/04/05 02:48:09 momjian Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
@ -2571,8 +2571,7 @@ set_config_option(const char *name, const char *value,
{ {
struct config_generic *record; struct config_generic *record;
int elevel; int elevel;
bool makeDefault; bool makeDefault, changeValOrig = changeVal;
bool changeVal_orig;
if (context == PGC_SIGHUP || source == PGC_S_DEFAULT) if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
elevel = DEBUG2; elevel = DEBUG2;
@ -2694,7 +2693,6 @@ set_config_option(const char *name, const char *value,
* to set the reset/session values even if we can't set the variable * to set the reset/session values even if we can't set the variable
* itself. * itself.
*/ */
changeVal_orig = changeVal; /* we might have to reverse this later */
if (record->source > source) if (record->source > source)
{ {
if (changeVal && !makeDefault) if (changeVal && !makeDefault)
@ -2703,11 +2701,15 @@ set_config_option(const char *name, const char *value,
name); name);
return true; return true;
} }
changeVal = false; /* we won't change the variable itself */ changeVal = false; /* this might be reset in USERLIMIT */
} }
/* /*
* Evaluate value and set variable * Evaluate value and set variable.
* USERLIMIT checks two things: 1) is the user making a change
* that is blocked by an administrator setting. 2) is the administrator
* changing a setting and doing a SIGHUP that requires us to override
* a user setting.
*/ */
switch (record->vartype) switch (record->vartype)
{ {
@ -2726,26 +2728,30 @@ set_config_option(const char *name, const char *value,
name))); name)));
return false; return false;
} }
/* Limit non-superuser changes */
if (record->context == PGC_USERLIMIT && if (record->context == PGC_USERLIMIT &&
source > PGC_S_UNPRIVILEGED && IsUnderPostmaster && !superuser())
newval < conf->reset_val &&
!superuser())
{ {
ereport(elevel, if (newval < conf->reset_val)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), {
errmsg("permission denied to set parameter \"%s\"", /* Limit non-superuser changes */
name), if (source > PGC_S_UNPRIVILEGED)
errhint("Must be superuser to change this value to false."))); {
return false; ereport(elevel,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to set parameter \"%s\"",
name),
errhint("Must be superuser to change this value to false.")));
return false;
}
}
if (newval > *conf->variable)
{
/* Allow change if admin should override */
if (source < PGC_S_UNPRIVILEGED &&
record->source > PGC_S_UNPRIVILEGED)
changeVal = changeValOrig;
}
} }
/* Honor change to config file with SIGHUP */
if (record->context == PGC_USERLIMIT &&
source < PGC_S_UNPRIVILEGED &&
record->reset_source > PGC_S_UNPRIVILEGED &&
newval > conf->reset_val &&
!superuser())
changeVal = changeVal_orig;
} }
else else
{ {
@ -2822,27 +2828,35 @@ set_config_option(const char *name, const char *value,
newval, name, conf->min, conf->max))); newval, name, conf->min, conf->max)));
return false; return false;
} }
/* Limit non-superuser changes */
if (record->context == PGC_USERLIMIT && if (record->context == PGC_USERLIMIT &&
source > PGC_S_UNPRIVILEGED && IsUnderPostmaster && !superuser())
conf->reset_val != 0 &&
(newval > conf->reset_val || newval == 0) &&
!superuser())
{ {
ereport(elevel, /* handle log_min_duration_statement, -1=disable */
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), if ((newval != -1 && conf->reset_val != -1 &&
errmsg("permission denied to set parameter \"%s\"", newval > conf->reset_val) || /* increase duration */
name), (newval == -1 && conf->reset_val != -1)) /* turn off */
errhint("Must be superuser to increase this value or set it to zero."))); {
return false; /* Limit non-superuser changes */
if (source > PGC_S_UNPRIVILEGED)
{
ereport(elevel,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to set parameter \"%s\"",
name),
errhint("Must be superuser to increase this value or turn it off.")));
return false;
}
}
/* Allow change if admin should override */
if ((newval != -1 && *conf->variable != -1 &&
newval < *conf->variable) || /* decrease duration */
(newval != -1 && *conf->variable == -1)) /* turn on */
{
if (source < PGC_S_UNPRIVILEGED &&
record->source > PGC_S_UNPRIVILEGED)
changeVal = changeValOrig;
}
} }
/* Honor change to config file with SIGHUP */
if (record->context == PGC_USERLIMIT &&
source < PGC_S_UNPRIVILEGED &&
record->reset_source > PGC_S_UNPRIVILEGED &&
newval < conf->reset_val && newval != 0 &&
!superuser())
changeVal = changeVal_orig;
} }
else else
{ {
@ -2919,26 +2933,25 @@ set_config_option(const char *name, const char *value,
newval, name, conf->min, conf->max))); newval, name, conf->min, conf->max)));
return false; return false;
} }
/* Limit non-superuser changes */
if (record->context == PGC_USERLIMIT && if (record->context == PGC_USERLIMIT &&
source > PGC_S_UNPRIVILEGED && IsUnderPostmaster && !superuser())
newval > conf->reset_val && /* No REAL PGC_USERLIMIT */
!superuser())
{ {
ereport(elevel, /* Limit non-superuser changes */
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), if (source > PGC_S_UNPRIVILEGED)
errmsg("permission denied to set parameter \"%s\"", {
name), ereport(elevel,
errhint("Must be superuser to increase this value."))); (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
return false; errmsg("permission denied to set parameter \"%s\"",
name),
errhint("Must be superuser to increase this value or turn it off.")));
return false;
}
/* Allow change if admin should override */
if (source < PGC_S_UNPRIVILEGED &&
record->source > PGC_S_UNPRIVILEGED)
changeVal = false;
} }
/* Honor change to config file with SIGHUP */
if (record->context == PGC_USERLIMIT &&
source < PGC_S_UNPRIVILEGED &&
record->reset_source > PGC_S_UNPRIVILEGED &&
newval < conf->reset_val &&
!superuser())
changeVal = changeVal_orig;
} }
else else
{ {
@ -3009,34 +3022,38 @@ set_config_option(const char *name, const char *value,
} }
if (record->context == PGC_USERLIMIT && if (record->context == PGC_USERLIMIT &&
*conf->variable) IsUnderPostmaster && !superuser())
{ {
int old_int_value, int old_int_value,
new_int_value; new_int_value;
/* all USERLIMIT strings are message levels */ /* all USERLIMIT strings are message levels */
assign_msglvl(&old_int_value, conf->reset_val,
true, source);
assign_msglvl(&new_int_value, newval, assign_msglvl(&new_int_value, newval,
true, source); true, source);
/* Limit non-superuser changes */ assign_msglvl(&old_int_value, conf->reset_val,
if (source > PGC_S_UNPRIVILEGED && true, source);
new_int_value > old_int_value && if (new_int_value > old_int_value)
!superuser())
{ {
ereport(elevel, /* Limit non-superuser changes */
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), if (source > PGC_S_UNPRIVILEGED)
{
ereport(elevel,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to set parameter \"%s\"", errmsg("permission denied to set parameter \"%s\"",
name), name),
errhint("Must be superuser to increase this value."))); errhint("Must be superuser to increase this value.")));
return false; return false;
}
}
/* Allow change if admin should override */
assign_msglvl(&old_int_value, *conf->variable,
true, source);
if (new_int_value < old_int_value)
{
if (source < PGC_S_UNPRIVILEGED &&
record->source > PGC_S_UNPRIVILEGED)
changeVal = changeValOrig;
} }
/* Honor change to config file with SIGHUP */
if (source < PGC_S_UNPRIVILEGED &&
record->reset_source > PGC_S_UNPRIVILEGED &&
newval < conf->reset_val &&
!superuser())
changeVal = changeVal_orig;
} }
} }
else if (conf->reset_val) else if (conf->reset_val)