Skip to content

Commit 89da5dc

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 34684ce commit 89da5dc

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
@@ -894,6 +894,11 @@ PostmasterMain(int argc, char *argv[])
894894
*/
895895
set_max_safe_fds();
896896

897+
/*
898+
* Set reference point for stack-depth checking.
899+
*/
900+
set_stack_base();
901+
897902
/*
898903
* Initialize the list of active backends.
899904
*/
@@ -3846,6 +3851,11 @@ SubPostmasterMain(int argc, char *argv[])
38463851
memset(&port, 0, sizeof(Port));
38473852
read_backend_variables(argv[2], &port);
38483853

3854+
/*
3855+
* Set reference point for stack-depth checking
3856+
*/
3857+
set_stack_base();
3858+
38493859
/*
38503860
* Set up memory area for GSS information. Mirrors the code in ConnCreate
38513861
* for the non-exec case.

src/backend/tcop/postgres.c

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

108108
/*
109-
* Stack base pointer -- initialized by PostgresMain. This is not static
110-
* so that PL/Java can modify it.
109+
* Stack base pointer -- initialized by PostmasterMain and inherited by
110+
* subprocesses. This is not static because old versions of PL/Java modify
111+
* it directly. Newer versions use set_stack_base(), but we want to stay
112+
* binary-compatible for the time being.
111113
*/
112114
char *stack_base_ptr = NULL;
113115

@@ -2719,6 +2721,53 @@ ia64_get_bsp(void)
27192721
#endif /* IA64 */
27202722

27212723

2724+
/*
2725+
* set_stack_base: set up reference point for stack depth checking
2726+
*
2727+
* Returns the old reference point, if any.
2728+
*/
2729+
pg_stack_base_t
2730+
set_stack_base(void)
2731+
{
2732+
char stack_base;
2733+
pg_stack_base_t old;
2734+
2735+
#if defined(__ia64__) || defined(__ia64)
2736+
old.stack_base_ptr = stack_base_ptr;
2737+
old.register_stack_base_ptr = register_stack_base_ptr;
2738+
#else
2739+
old = stack_base_ptr;
2740+
#endif
2741+
2742+
/* Set up reference point for stack depth checking */
2743+
stack_base_ptr = &stack_base;
2744+
#if defined(__ia64__) || defined(__ia64)
2745+
register_stack_base_ptr = ia64_get_bsp();
2746+
#endif
2747+
2748+
return old;
2749+
}
2750+
2751+
/*
2752+
* restore_stack_base: restore reference point for stack depth checking
2753+
*
2754+
* This can be used after set_stack_base() to restore the old value. This
2755+
* is currently only used in PL/Java. When PL/Java calls a backend function
2756+
* from different thread, the thread's stack is at a different location than
2757+
* the main thread's stack, so it sets the base pointer before the call, and
2758+
* restores it afterwards.
2759+
*/
2760+
void
2761+
restore_stack_base(pg_stack_base_t base)
2762+
{
2763+
#if defined(__ia64__) || defined(__ia64)
2764+
stack_base_ptr = base.stack_base_ptr;
2765+
register_stack_base_ptr = base.register_stack_base_ptr;
2766+
#else
2767+
stack_base_ptr = base;
2768+
#endif
2769+
}
2770+
27222771
/*
27232772
* check_stack_depth: check for excessively deep recursion
27242773
*
@@ -2734,7 +2783,7 @@ check_stack_depth(void)
27342783
long stack_depth;
27352784

27362785
/*
2737-
* Compute distance from PostgresMain's local variables to my own
2786+
* Compute distance from reference point to to my local variables
27382787
*/
27392788
stack_depth = (long) (stack_base_ptr - &stack_top_loc);
27402789

@@ -2927,7 +2976,6 @@ PostgresMain(int argc, char *argv[], const char *username)
29272976
GucSource gucsource;
29282977
bool am_superuser;
29292978
int firstchar;
2930-
char stack_base;
29312979
StringInfoData input_message;
29322980
sigjmp_buf local_sigjmp_buf;
29332981
volatile bool send_ready_for_query = true;
@@ -2957,10 +3005,7 @@ PostgresMain(int argc, char *argv[], const char *username)
29573005
SetProcessingMode(InitProcessing);
29583006

29593007
/* Set up reference point for stack depth checking */
2960-
stack_base_ptr = &stack_base;
2961-
#if defined(__ia64__) || defined(__ia64)
2962-
register_stack_base_ptr = ia64_get_bsp();
2963-
#endif
3008+
set_stack_base();
29643009

29653010
/* Compute paths, if we didn't inherit them from postmaster */
29663011
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

0 commit comments

Comments
 (0)