Commit ef3883d1 authored by Heikki Linnakangas's avatar Heikki Linnakangas

Do stack-depth checking in all postmaster children.

We used to only initialize the stack base pointer when starting up a regular
backend, not in other processes. In particular, autovacuum workers can run
arbitrary user code, and without stack-depth checking, infinite recursion
in e.g an index expression will bring down the whole cluster.

The comment about PL/Java using set_stack_base() is not yet true. As the
code stands, PL/java still modifies the stack_base_ptr variable directly.
However, it's been discussed in the PL/Java mailing list that it should be
changed to use the function, because PL/Java is currently oblivious to the
register stack used on Itanium. There's another issues with PL/Java, namely
that the stack base pointer it sets is not really the base of the stack, it
could be something close to the bottom of the stack. That's a separate issue
that might need some further changes to this code, but that's a different
story.

Backpatch to all supported releases.
parent 7feecedc
...@@ -970,6 +970,11 @@ PostmasterMain(int argc, char *argv[]) ...@@ -970,6 +970,11 @@ PostmasterMain(int argc, char *argv[])
*/ */
set_max_safe_fds(); set_max_safe_fds();
/*
* Set reference point for stack-depth checking.
*/
set_stack_base();
/* /*
* Initialize the list of active backends. * Initialize the list of active backends.
*/ */
...@@ -3977,6 +3982,11 @@ SubPostmasterMain(int argc, char *argv[]) ...@@ -3977,6 +3982,11 @@ SubPostmasterMain(int argc, char *argv[])
memset(&port, 0, sizeof(Port)); memset(&port, 0, sizeof(Port));
read_backend_variables(argv[2], &port); read_backend_variables(argv[2], &port);
/*
* Set reference point for stack-depth checking
*/
set_stack_base();
/* /*
* Set up memory area for GSS information. Mirrors the code in ConnCreate * Set up memory area for GSS information. Mirrors the code in ConnCreate
* for the non-exec case. * for the non-exec case.
......
...@@ -115,8 +115,10 @@ int PostAuthDelay = 0; ...@@ -115,8 +115,10 @@ int PostAuthDelay = 0;
static long max_stack_depth_bytes = 100 * 1024L; static long max_stack_depth_bytes = 100 * 1024L;
/* /*
* Stack base pointer -- initialized by PostgresMain. This is not static * Stack base pointer -- initialized by PostmasterMain and inherited by
* so that PL/Java can modify it. * subprocesses. This is not static because old versions of PL/Java modify
* it directly. Newer versions use set_stack_base(), but we want to stay
* binary-compatible for the time being.
*/ */
char *stack_base_ptr = NULL; char *stack_base_ptr = NULL;
...@@ -2957,6 +2959,53 @@ ia64_get_bsp(void) ...@@ -2957,6 +2959,53 @@ ia64_get_bsp(void)
#endif /* IA64 */ #endif /* IA64 */
/*
* set_stack_base: set up reference point for stack depth checking
*
* Returns the old reference point, if any.
*/
pg_stack_base_t
set_stack_base(void)
{
char stack_base;
pg_stack_base_t old;
#if defined(__ia64__) || defined(__ia64)
old.stack_base_ptr = stack_base_ptr;
old.register_stack_base_ptr = register_stack_base_ptr;
#else
old = stack_base_ptr;
#endif
/* Set up reference point for stack depth checking */
stack_base_ptr = &stack_base;
#if defined(__ia64__) || defined(__ia64)
register_stack_base_ptr = ia64_get_bsp();
#endif
return old;
}
/*
* restore_stack_base: restore reference point for stack depth checking
*
* This can be used after set_stack_base() to restore the old value. This
* is currently only used in PL/Java. When PL/Java calls a backend function
* from different thread, the thread's stack is at a different location than
* the main thread's stack, so it sets the base pointer before the call, and
* restores it afterwards.
*/
void
restore_stack_base(pg_stack_base_t base)
{
#if defined(__ia64__) || defined(__ia64)
stack_base_ptr = base.stack_base_ptr;
register_stack_base_ptr = base.register_stack_base_ptr;
#else
stack_base_ptr = base;
#endif
}
/* /*
* check_stack_depth: check for excessively deep recursion * check_stack_depth: check for excessively deep recursion
* *
...@@ -2972,7 +3021,7 @@ check_stack_depth(void) ...@@ -2972,7 +3021,7 @@ check_stack_depth(void)
long stack_depth; long stack_depth;
/* /*
* Compute distance from PostgresMain's local variables to my own * Compute distance from reference point to to my local variables
*/ */
stack_depth = (long) (stack_base_ptr - &stack_top_loc); stack_depth = (long) (stack_base_ptr - &stack_top_loc);
...@@ -3434,7 +3483,6 @@ PostgresMain(int argc, char *argv[], const char *username) ...@@ -3434,7 +3483,6 @@ PostgresMain(int argc, char *argv[], const char *username)
{ {
const char *dbname; const char *dbname;
int firstchar; int firstchar;
char stack_base;
StringInfoData input_message; StringInfoData input_message;
sigjmp_buf local_sigjmp_buf; sigjmp_buf local_sigjmp_buf;
volatile bool send_ready_for_query = true; volatile bool send_ready_for_query = true;
...@@ -3461,10 +3509,7 @@ PostgresMain(int argc, char *argv[], const char *username) ...@@ -3461,10 +3509,7 @@ PostgresMain(int argc, char *argv[], const char *username)
SetProcessingMode(InitProcessing); SetProcessingMode(InitProcessing);
/* Set up reference point for stack depth checking */ /* Set up reference point for stack depth checking */
stack_base_ptr = &stack_base; set_stack_base();
#if defined(__ia64__) || defined(__ia64)
register_stack_base_ptr = ia64_get_bsp();
#endif
/* Compute paths, if we didn't inherit them from postmaster */ /* Compute paths, if we didn't inherit them from postmaster */
if (my_exec_path[0] == '\0') if (my_exec_path[0] == '\0')
......
...@@ -246,6 +246,19 @@ extern bool VacuumCostActive; ...@@ -246,6 +246,19 @@ extern bool VacuumCostActive;
/* in tcop/postgres.c */ /* in tcop/postgres.c */
#if defined(__ia64__) || defined(__ia64)
typedef struct
{
char *stack_base_ptr;
char *register_stack_base_ptr;
} pg_stack_base_t;
#else
typedef char *pg_stack_base_t;
#endif
extern pg_stack_base_t set_stack_base(void);
extern void restore_stack_base(pg_stack_base_t base);
extern void check_stack_depth(void); extern void check_stack_depth(void);
/* in tcop/utility.c */ /* in tcop/utility.c */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment