diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-04-08 18:28:12 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-04-08 19:08:13 +0300 |
commit | ef29bb1f7254222835267cc03389ed12602c677c (patch) | |
tree | 985f3562c0a8de92789faf074bb3ff0eaa964111 /src/backend/tcop/postgres.c | |
parent | 63d8636c50f2ca053aa6a214340bb322bc5687d5 (diff) | |
download | postgresql-ef29bb1f7254222835267cc03389ed12602c677c.tar.gz postgresql-ef29bb1f7254222835267cc03389ed12602c677c.zip |
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.
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r-- | src/backend/tcop/postgres.c | 61 |
1 files changed, 53 insertions, 8 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 660a67412dc..638ba0fe066 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -114,8 +114,10 @@ int PostAuthDelay = 0; static long max_stack_depth_bytes = 100 * 1024L; /* - * Stack base pointer -- initialized by PostgresMain. This is not static - * so that PL/Java can modify it. + * Stack base pointer -- initialized by PostmasterMain and inherited by + * 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; @@ -3003,6 +3005,53 @@ ia64_get_bsp(void) /* + * 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 * * This should be called someplace in any recursive routine that might possibly @@ -3017,7 +3066,7 @@ check_stack_depth(void) 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); @@ -3459,7 +3508,6 @@ PostgresMain(int argc, char *argv[], const char *username) { const char *dbname; int firstchar; - char stack_base; StringInfoData input_message; sigjmp_buf local_sigjmp_buf; volatile bool send_ready_for_query = true; @@ -3486,10 +3534,7 @@ PostgresMain(int argc, char *argv[], const char *username) SetProcessingMode(InitProcessing); /* 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 + set_stack_base(); /* Compute paths, if we didn't inherit them from postmaster */ if (my_exec_path[0] == '\0') |