Skip to content

Commit c4a586c

Browse files
committed
Prevent possible crash reading pg_stat_activity.
Also, avoid reading PGPROC's wait_event field twice, once for the wait event and again for the wait_event_type, because the value might change in the middle. Petr Jelinek and Robert Haas
1 parent 36f69fa commit c4a586c

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

src/backend/utils/adt/pgstatfuncs.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "utils/inet.h"
2828
#include "utils/timestamp.h"
2929

30+
#define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var))))
31+
3032
/* bogus ... these externs should be in a header file */
3133
extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
3234
extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS);
@@ -783,13 +785,26 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
783785
values[5] = CStringGetTextDatum(beentry->st_activity);
784786

785787
proc = BackendPidGetProc(beentry->st_procpid);
786-
wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info);
788+
if (proc != NULL)
789+
{
790+
uint32 raw_wait_event;
791+
792+
raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info);
793+
wait_event_type = pgstat_get_wait_event_type(raw_wait_event);
794+
wait_event = pgstat_get_wait_event(raw_wait_event);
795+
796+
}
797+
else
798+
{
799+
wait_event_type = NULL;
800+
wait_event = NULL;
801+
}
802+
787803
if (wait_event_type)
788804
values[6] = CStringGetTextDatum(wait_event_type);
789805
else
790806
nulls[6] = true;
791807

792-
wait_event = pgstat_get_wait_event(proc->wait_event_info);
793808
if (wait_event)
794809
values[7] = CStringGetTextDatum(wait_event);
795810
else
@@ -984,17 +999,14 @@ pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS)
984999
int32 beid = PG_GETARG_INT32(0);
9851000
PgBackendStatus *beentry;
9861001
PGPROC *proc;
987-
const char *wait_event_type;
1002+
const char *wait_event_type = NULL;
9881003

9891004
if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
9901005
wait_event_type = "<backend information not available>";
9911006
else if (!has_privs_of_role(GetUserId(), beentry->st_userid))
9921007
wait_event_type = "<insufficient privilege>";
993-
else
994-
{
995-
proc = BackendPidGetProc(beentry->st_procpid);
1008+
else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
9961009
wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info);
997-
}
9981010

9991011
if (!wait_event_type)
10001012
PG_RETURN_NULL();
@@ -1008,17 +1020,14 @@ pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS)
10081020
int32 beid = PG_GETARG_INT32(0);
10091021
PgBackendStatus *beentry;
10101022
PGPROC *proc;
1011-
const char *wait_event;
1023+
const char *wait_event = NULL;
10121024

10131025
if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
10141026
wait_event = "<backend information not available>";
10151027
else if (!has_privs_of_role(GetUserId(), beentry->st_userid))
10161028
wait_event = "<insufficient privilege>";
1017-
else
1018-
{
1019-
proc = BackendPidGetProc(beentry->st_procpid);
1029+
else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
10201030
wait_event = pgstat_get_wait_event(proc->wait_event_info);
1021-
}
10221031

10231032
if (!wait_event)
10241033
PG_RETURN_NULL();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy