I have just applied the attached patch:
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.
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.195
diff -c -c -r1.195 guc.c
*** src/backend/utils/misc/guc.c 1 Apr 2004 21:28:45 -0000 1.195
--- src/backend/utils/misc/guc.c 5 Apr 2004 02:35:08 -0000
***************
*** 2571,2578 ****
{
struct config_generic *record;
int elevel;
! bool makeDefault;
! bool changeVal_orig;
if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
elevel = DEBUG2;
--- 2571,2577 ----
{
struct config_generic *record;
int elevel;
! bool makeDefault, changeValOrig = changeVal;
if (context == PGC_SIGHUP || source == PGC_S_DEFAULT)
elevel = DEBUG2;
***************
*** 2694,2700 ****
* to set the reset/session values even if we can't set the variable
* itself.
*/
- changeVal_orig = changeVal; /* we might have to reverse this later */
if (record->source > source)
{
if (changeVal && !makeDefault)
--- 2693,2698 ----
***************
*** 2703,2713 ****
name);
return true;
}
! changeVal = false; /* we won't change the variable itself */
}
/*
! * Evaluate value and set variable
*/
switch (record->vartype)
{
--- 2701,2715 ----
name);
return true;
}
! changeVal = false; /* this might be reset in USERLIMIT */
}
/*
! * 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)
{
***************
*** 2726,2751 ****
name)));
return false;
}
- /* Limit non-superuser changes */
if (record->context == PGC_USERLIMIT &&
! source > PGC_S_UNPRIVILEGED &&
! newval < conf->reset_val &&
! !superuser())
{
! 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;
}
- /* 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
{
--- 2728,2757 ----
name)));
return false;
}
if (record->context == PGC_USERLIMIT &&
! IsUnderPostmaster && !superuser())
{
! if (newval < conf->reset_val)
! {
! /* 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 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;
! }
}
}
else
{
***************
*** 2822,2848 ****
newval, name, conf->min, conf->max)));
return false;
}
- /* Limit non-superuser changes */
if (record->context == PGC_USERLIMIT &&
! source > PGC_S_UNPRIVILEGED &&
! conf->reset_val != 0 &&
! (newval > conf->reset_val || newval == 0) &&
! !superuser())
{
! ereport(elevel,
! (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! errmsg("permission denied to set parameter \"%s\"",
! name),
! errhint("Must be superuser to increase this value or set it to zero.")));
! return 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 && newval != 0 &&
- !superuser())
- changeVal = changeVal_orig;
}
else
{
--- 2828,2862 ----
newval, name, conf->min, conf->max)));
return false;
}
if (record->context == PGC_USERLIMIT &&
! IsUnderPostmaster && !superuser())
{
! /* handle log_min_duration_statement, -1=disable */
! if ((newval != -1 && conf->reset_val != -1 &&
! newval > conf->reset_val) || /* increase duration */
! (newval == -1 && conf->reset_val != -1)) /* turn off */
! {
! /* 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;
! }
}
}
else
{
***************
*** 2919,2944 ****
newval, name, conf->min, conf->max)));
return false;
}
- /* Limit non-superuser changes */
if (record->context == PGC_USERLIMIT &&
! source > PGC_S_UNPRIVILEGED &&
! newval > conf->reset_val &&
! !superuser())
{
! ereport(elevel,
! (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! errmsg("permission denied to set parameter \"%s\"",
! name),
! errhint("Must be superuser to increase this value.")));
! return 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
{
--- 2933,2957 ----
newval, name, conf->min, conf->max)));
return false;
}
if (record->context == PGC_USERLIMIT &&
! IsUnderPostmaster && !superuser())
! /* No REAL PGC_USERLIMIT */
{
! /* 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 (source < PGC_S_UNPRIVILEGED &&
! record->source > PGC_S_UNPRIVILEGED)
! changeVal = false;
}
}
else
{
***************
*** 3009,3042 ****
}
if (record->context == PGC_USERLIMIT &&
! *conf->variable)
{
int old_int_value,
new_int_value;
/* all USERLIMIT strings are message levels */
- assign_msglvl(&old_int_value, conf->reset_val,
- true, source);
assign_msglvl(&new_int_value, newval,
true, source);
! /* Limit non-superuser changes */
! if (source > PGC_S_UNPRIVILEGED &&
! new_int_value > old_int_value &&
! !superuser())
{
! ereport(elevel,
! (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to set parameter \"%s\"",
name),
! errhint("Must be superuser to increase this value.")));
! return false;
}
- /* 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)
--- 3022,3059 ----
}
if (record->context == PGC_USERLIMIT &&
! IsUnderPostmaster && !superuser())
{
int old_int_value,
new_int_value;
/* all USERLIMIT strings are message levels */
assign_msglvl(&new_int_value, newval,
true, source);
! assign_msglvl(&old_int_value, conf->reset_val,
! true, source);
! if (new_int_value > old_int_value)
{
! /* 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.")));
! 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;
}
}
}
else if (conf->reset_val)