Skip to content

Commit 77dc2b0

Browse files
committed
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.
1 parent f42a4c0 commit 77dc2b0

File tree

3 files changed

+76
-8
lines changed

3 files changed

+76
-8
lines changed

src/backend/postmaster/postmaster.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,11 @@ PostmasterMain(int argc, char *argv[])
946946
*/
947947
set_max_safe_fds();
948948

949+
/*
950+
* Set reference point for stack-depth checking.
951+
*/
952+
set_stack_base();
953+
949954
/*
950955
* Initialize the list of active backends.
951956
*/
@@ -3944,6 +3949,11 @@ SubPostmasterMain(int argc, char *argv[])
39443949
memset(&port, 0, sizeof(Port));
39453950
read_backend_variables(argv[2], &port);
39463951

3952+
/*
3953+
* Set reference point for stack-depth checking
3954+
*/
3955+
set_stack_base();
3956+
39473957
/*
39483958
* Set up memory area for GSS information. Mirrors the code in ConnCreate
39493959
* for the non-exec case.

src/backend/tcop/postgres.c

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ int PostAuthDelay = 0;
113113
static long max_stack_depth_bytes = 100 * 1024L;
114114

115115
/*
116-
* Stack base pointer -- initialized by PostgresMain. This is not static
117-
* so that PL/Java can modify it.
116+
* Stack base pointer -- initialized by PostmasterMain and inherited by
117+
* subprocesses. This is not static because old versions of PL/Java modify
118+
* it directly. Newer versions use set_stack_base(), but we want to stay
119+
* binary-compatible for the time being.
118120
*/
119121
char *stack_base_ptr = NULL;
120122

@@ -3024,6 +3026,53 @@ ia64_get_bsp(void)
30243026
#endif /* IA64 */
30253027

30263028

3029+
/*
3030+
* set_stack_base: set up reference point for stack depth checking
3031+
*
3032+
* Returns the old reference point, if any.
3033+
*/
3034+
pg_stack_base_t
3035+
set_stack_base(void)
3036+
{
3037+
char stack_base;
3038+
pg_stack_base_t old;
3039+
3040+
#if defined(__ia64__) || defined(__ia64)
3041+
old.stack_base_ptr = stack_base_ptr;
3042+
old.register_stack_base_ptr = register_stack_base_ptr;
3043+
#else
3044+
old = stack_base_ptr;
3045+
#endif
3046+
3047+
/* Set up reference point for stack depth checking */
3048+
stack_base_ptr = &stack_base;
3049+
#if defined(__ia64__) || defined(__ia64)
3050+
register_stack_base_ptr = ia64_get_bsp();
3051+
#endif
3052+
3053+
return old;
3054+
}
3055+
3056+
/*
3057+
* restore_stack_base: restore reference point for stack depth checking
3058+
*
3059+
* This can be used after set_stack_base() to restore the old value. This
3060+
* is currently only used in PL/Java. When PL/Java calls a backend function
3061+
* from different thread, the thread's stack is at a different location than
3062+
* the main thread's stack, so it sets the base pointer before the call, and
3063+
* restores it afterwards.
3064+
*/
3065+
void
3066+
restore_stack_base(pg_stack_base_t base)
3067+
{
3068+
#if defined(__ia64__) || defined(__ia64)
3069+
stack_base_ptr = base.stack_base_ptr;
3070+
register_stack_base_ptr = base.register_stack_base_ptr;
3071+
#else
3072+
stack_base_ptr = base;
3073+
#endif
3074+
}
3075+
30273076
/*
30283077
* check_stack_depth: check for excessively deep recursion
30293078
*
@@ -3039,7 +3088,7 @@ check_stack_depth(void)
30393088
long stack_depth;
30403089

30413090
/*
3042-
* Compute distance from PostgresMain's local variables to my own
3091+
* Compute distance from reference point to to my local variables
30433092
*/
30443093
stack_depth = (long) (stack_base_ptr - &stack_top_loc);
30453094

@@ -3469,7 +3518,6 @@ PostgresMain(int argc, char *argv[], const char *username)
34693518
{
34703519
const char *dbname;
34713520
int firstchar;
3472-
char stack_base;
34733521
StringInfoData input_message;
34743522
sigjmp_buf local_sigjmp_buf;
34753523
volatile bool send_ready_for_query = true;
@@ -3496,10 +3544,7 @@ PostgresMain(int argc, char *argv[], const char *username)
34963544
SetProcessingMode(InitProcessing);
34973545

34983546
/* Set up reference point for stack depth checking */
3499-
stack_base_ptr = &stack_base;
3500-
#if defined(__ia64__) || defined(__ia64)
3501-
register_stack_base_ptr = ia64_get_bsp();
3502-
#endif
3547+
set_stack_base();
35033548

35043549
/* Compute paths, if we didn't inherit them from postmaster */
35053550
if (my_exec_path[0] == '\0')

src/include/miscadmin.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,19 @@ extern bool VacuumCostActive;
234234

235235

236236
/* in tcop/postgres.c */
237+
238+
#if defined(__ia64__) || defined(__ia64)
239+
typedef struct
240+
{
241+
char *stack_base_ptr;
242+
char *register_stack_base_ptr;
243+
} pg_stack_base_t;
244+
#else
245+
typedef char *pg_stack_base_t;
246+
#endif
247+
248+
extern pg_stack_base_t set_stack_base(void);
249+
extern void restore_stack_base(pg_stack_base_t base);
237250
extern void check_stack_depth(void);
238251

239252
/* in tcop/utility.c */

0 commit comments

Comments
 (0)