Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ef3883d

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 7feeced commit ef3883d

File tree

3 files changed

+76
-8
lines changed

3 files changed

+76
-8
lines changed

src/backend/postmaster/postmaster.c

+10
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,11 @@ PostmasterMain(int argc, char *argv[])
970970
*/
971971
set_max_safe_fds();
972972

973+
/*
974+
* Set reference point for stack-depth checking.
975+
*/
976+
set_stack_base();
977+
973978
/*
974979
* Initialize the list of active backends.
975980
*/
@@ -3977,6 +3982,11 @@ SubPostmasterMain(int argc, char *argv[])
39773982
memset(&port, 0, sizeof(Port));
39783983
read_backend_variables(argv[2], &port);
39793984

3985+
/*
3986+
* Set reference point for stack-depth checking
3987+
*/
3988+
set_stack_base();
3989+
39803990
/*
39813991
* Set up memory area for GSS information. Mirrors the code in ConnCreate
39823992
* for the non-exec case.

src/backend/tcop/postgres.c

+53-8
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ int PostAuthDelay = 0;
115115
static long max_stack_depth_bytes = 100 * 1024L;
116116

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

@@ -2957,6 +2959,53 @@ ia64_get_bsp(void)
29572959
#endif /* IA64 */
29582960

29592961

2962+
/*
2963+
* set_stack_base: set up reference point for stack depth checking
2964+
*
2965+
* Returns the old reference point, if any.
2966+
*/
2967+
pg_stack_base_t
2968+
set_stack_base(void)
2969+
{
2970+
char stack_base;
2971+
pg_stack_base_t old;
2972+
2973+
#if defined(__ia64__) || defined(__ia64)
2974+
old.stack_base_ptr = stack_base_ptr;
2975+
old.register_stack_base_ptr = register_stack_base_ptr;
2976+
#else
2977+
old = stack_base_ptr;
2978+
#endif
2979+
2980+
/* Set up reference point for stack depth checking */
2981+
stack_base_ptr = &stack_base;
2982+
#if defined(__ia64__) || defined(__ia64)
2983+
register_stack_base_ptr = ia64_get_bsp();
2984+
#endif
2985+
2986+
return old;
2987+
}
2988+
2989+
/*
2990+
* restore_stack_base: restore reference point for stack depth checking
2991+
*
2992+
* This can be used after set_stack_base() to restore the old value. This
2993+
* is currently only used in PL/Java. When PL/Java calls a backend function
2994+
* from different thread, the thread's stack is at a different location than
2995+
* the main thread's stack, so it sets the base pointer before the call, and
2996+
* restores it afterwards.
2997+
*/
2998+
void
2999+
restore_stack_base(pg_stack_base_t base)
3000+
{
3001+
#if defined(__ia64__) || defined(__ia64)
3002+
stack_base_ptr = base.stack_base_ptr;
3003+
register_stack_base_ptr = base.register_stack_base_ptr;
3004+
#else
3005+
stack_base_ptr = base;
3006+
#endif
3007+
}
3008+
29603009
/*
29613010
* check_stack_depth: check for excessively deep recursion
29623011
*
@@ -2972,7 +3021,7 @@ check_stack_depth(void)
29723021
long stack_depth;
29733022

29743023
/*
2975-
* Compute distance from PostgresMain's local variables to my own
3024+
* Compute distance from reference point to to my local variables
29763025
*/
29773026
stack_depth = (long) (stack_base_ptr - &stack_top_loc);
29783027

@@ -3434,7 +3483,6 @@ PostgresMain(int argc, char *argv[], const char *username)
34343483
{
34353484
const char *dbname;
34363485
int firstchar;
3437-
char stack_base;
34383486
StringInfoData input_message;
34393487
sigjmp_buf local_sigjmp_buf;
34403488
volatile bool send_ready_for_query = true;
@@ -3461,10 +3509,7 @@ PostgresMain(int argc, char *argv[], const char *username)
34613509
SetProcessingMode(InitProcessing);
34623510

34633511
/* Set up reference point for stack depth checking */
3464-
stack_base_ptr = &stack_base;
3465-
#if defined(__ia64__) || defined(__ia64)
3466-
register_stack_base_ptr = ia64_get_bsp();
3467-
#endif
3512+
set_stack_base();
34683513

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

src/include/miscadmin.h

+13
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,19 @@ extern bool VacuumCostActive;
246246

247247

248248
/* in tcop/postgres.c */
249+
250+
#if defined(__ia64__) || defined(__ia64)
251+
typedef struct
252+
{
253+
char *stack_base_ptr;
254+
char *register_stack_base_ptr;
255+
} pg_stack_base_t;
256+
#else
257+
typedef char *pg_stack_base_t;
258+
#endif
259+
260+
extern pg_stack_base_t set_stack_base(void);
261+
extern void restore_stack_base(pg_stack_base_t base);
249262
extern void check_stack_depth(void);
250263

251264
/* in tcop/utility.c */

0 commit comments

Comments
 (0)