!1 CVE-2020-21469 安全更新:In-the-postmaster-rely-on-the-signal-infrastructure
Merge pull request !1 from 吴诚/openkylin/yangtze
This commit is contained in:
commit
aafdb4ff4f
|
@ -95,3 +95,52 @@ pqinitmask(void)
|
||||||
sigdelset(&StartupBlockSig, SIGALRM);
|
sigdelset(&StartupBlockSig, SIGALRM);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up a postmaster signal handler for signal "signo"
|
||||||
|
*
|
||||||
|
* Returns the previous handler.
|
||||||
|
*
|
||||||
|
* This is used only in the postmaster, which has its own odd approach to
|
||||||
|
* signal handling. For signals with handlers, we block all signals for the
|
||||||
|
* duration of signal handler execution. We also do not set the SA_RESTART
|
||||||
|
* flag; this should be safe given the tiny range of code in which the
|
||||||
|
* postmaster ever unblocks signals.
|
||||||
|
*
|
||||||
|
* pqinitmask() must have been invoked previously.
|
||||||
|
*
|
||||||
|
* On Windows, this function is just an alias for pqsignal()
|
||||||
|
* (and note that it's calling the code in src/backend/port/win32/signal.c,
|
||||||
|
* not src/port/pqsignal.c). On that platform, the postmaster's signal
|
||||||
|
* handlers still have to block signals for themselves.
|
||||||
|
*/
|
||||||
|
pqsigfunc
|
||||||
|
pqsignal_pm(int signo, pqsigfunc func)
|
||||||
|
{
|
||||||
|
#ifndef WIN32
|
||||||
|
struct sigaction act,
|
||||||
|
oact;
|
||||||
|
|
||||||
|
act.sa_handler = func;
|
||||||
|
if (func == SIG_IGN || func == SIG_DFL)
|
||||||
|
{
|
||||||
|
/* in these cases, act the same as pqsignal() */
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
act.sa_flags = SA_RESTART;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
act.sa_mask = BlockSig;
|
||||||
|
act.sa_flags = 0;
|
||||||
|
}
|
||||||
|
#ifdef SA_NOCLDSTOP
|
||||||
|
if (signo == SIGCHLD)
|
||||||
|
act.sa_flags |= SA_NOCLDSTOP;
|
||||||
|
#endif
|
||||||
|
if (sigaction(signo, &act, &oact) < 0)
|
||||||
|
return SIG_ERR;
|
||||||
|
return oact.sa_handler;
|
||||||
|
#else /* WIN32 */
|
||||||
|
return pqsignal(signo, func);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -606,14 +606,25 @@ PostmasterMain(int argc, char *argv[])
|
||||||
/*
|
/*
|
||||||
* Set up signal handlers for the postmaster process.
|
* Set up signal handlers for the postmaster process.
|
||||||
*
|
*
|
||||||
* In the postmaster, we want to install non-ignored handlers *without*
|
* In the postmaster, we use pqsignal_pm() rather than pqsignal() (which
|
||||||
* SA_RESTART. This is because they'll be blocked at all times except
|
* is used by all child processes and client processes). That has a
|
||||||
* when ServerLoop is waiting for something to happen, and during that
|
* couple of special behaviors:
|
||||||
* window, we want signals to exit the select(2) wait so that ServerLoop
|
*
|
||||||
* can respond if anything interesting happened. On some platforms,
|
* 1. Except on Windows, we tell sigaction() to block all signals for the
|
||||||
* signals marked SA_RESTART would not cause the select() wait to end.
|
* duration of the signal handler. This is faster than our old approach
|
||||||
* Child processes will generally want SA_RESTART, but we expect them to
|
* of blocking/unblocking explicitly in the signal handler, and it should
|
||||||
* set up their own handlers before unblocking signals.
|
* also prevent excessive stack consumption if signals arrive quickly.
|
||||||
|
*
|
||||||
|
* 2. We do not set the SA_RESTART flag. This is because signals will be
|
||||||
|
* blocked at all times except when ServerLoop is waiting for something to
|
||||||
|
* happen, and during that window, we want signals to exit the select(2)
|
||||||
|
* wait so that ServerLoop can respond if anything interesting happened.
|
||||||
|
* On some platforms, signals marked SA_RESTART would not cause the
|
||||||
|
* select() wait to end.
|
||||||
|
*
|
||||||
|
* Child processes will generally want SA_RESTART, so pqsignal() sets that
|
||||||
|
* flag. We expect children to set up their own handlers before
|
||||||
|
* unblocking signals.
|
||||||
*
|
*
|
||||||
* CAUTION: when changing this list, check for side-effects on the signal
|
* CAUTION: when changing this list, check for side-effects on the signal
|
||||||
* handling setup of child processes. See tcop/postgres.c,
|
* handling setup of child processes. See tcop/postgres.c,
|
||||||
|
@ -625,18 +636,16 @@ PostmasterMain(int argc, char *argv[])
|
||||||
pqinitmask();
|
pqinitmask();
|
||||||
PG_SETMASK(&BlockSig);
|
PG_SETMASK(&BlockSig);
|
||||||
|
|
||||||
pqsignal_no_restart(SIGHUP, SIGHUP_handler); /* reread config file and
|
pqsignal_pm(SIGHUP, SIGHUP_handler); /* reread config file and have
|
||||||
* have children do same */
|
* children do same */
|
||||||
pqsignal_no_restart(SIGINT, pmdie); /* send SIGTERM and shut down */
|
pqsignal_pm(SIGINT, pmdie); /* send SIGTERM and shut down */
|
||||||
pqsignal_no_restart(SIGQUIT, pmdie); /* send SIGQUIT and die */
|
pqsignal_pm(SIGQUIT, pmdie); /* send SIGQUIT and die */
|
||||||
pqsignal_no_restart(SIGTERM, pmdie); /* wait for children and shut down */
|
pqsignal_pm(SIGTERM, pmdie); /* wait for children and shut down */
|
||||||
pqsignal(SIGALRM, SIG_IGN); /* ignored */
|
pqsignal_pm(SIGALRM, SIG_IGN); /* ignored */
|
||||||
pqsignal(SIGPIPE, SIG_IGN); /* ignored */
|
pqsignal_pm(SIGPIPE, SIG_IGN); /* ignored */
|
||||||
pqsignal_no_restart(SIGUSR1, sigusr1_handler); /* message from child
|
pqsignal_pm(SIGUSR1, sigusr1_handler); /* message from child process */
|
||||||
* process */
|
pqsignal_pm(SIGUSR2, dummy_handler); /* unused, reserve for children */
|
||||||
pqsignal_no_restart(SIGUSR2, dummy_handler); /* unused, reserve for
|
pqsignal_pm(SIGCHLD, reaper); /* handle child termination */
|
||||||
* children */
|
|
||||||
pqsignal_no_restart(SIGCHLD, reaper); /* handle child termination */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No other place in Postgres should touch SIGTTIN/SIGTTOU handling. We
|
* No other place in Postgres should touch SIGTTIN/SIGTTOU handling. We
|
||||||
|
@ -646,15 +655,15 @@ PostmasterMain(int argc, char *argv[])
|
||||||
* child processes should just allow the inherited settings to stand.
|
* child processes should just allow the inherited settings to stand.
|
||||||
*/
|
*/
|
||||||
#ifdef SIGTTIN
|
#ifdef SIGTTIN
|
||||||
pqsignal(SIGTTIN, SIG_IGN); /* ignored */
|
pqsignal_pm(SIGTTIN, SIG_IGN); /* ignored */
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGTTOU
|
#ifdef SIGTTOU
|
||||||
pqsignal(SIGTTOU, SIG_IGN); /* ignored */
|
pqsignal_pm(SIGTTOU, SIG_IGN); /* ignored */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ignore SIGXFSZ, so that ulimit violations work like disk full */
|
/* ignore SIGXFSZ, so that ulimit violations work like disk full */
|
||||||
#ifdef SIGXFSZ
|
#ifdef SIGXFSZ
|
||||||
pqsignal(SIGXFSZ, SIG_IGN); /* ignored */
|
pqsignal_pm(SIGXFSZ, SIG_IGN); /* ignored */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2627,7 +2636,13 @@ SIGHUP_handler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We rely on the signal mechanism to have blocked all signals ... except
|
||||||
|
* on Windows, which lacks sigaction(), so we have to do it manually.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&BlockSig);
|
PG_SETMASK(&BlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (Shutdown <= SmartShutdown)
|
if (Shutdown <= SmartShutdown)
|
||||||
{
|
{
|
||||||
|
@ -2687,7 +2702,9 @@ SIGHUP_handler(SIGNAL_ARGS)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&UnBlockSig);
|
PG_SETMASK(&UnBlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
@ -2701,7 +2718,13 @@ pmdie(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We rely on the signal mechanism to have blocked all signals ... except
|
||||||
|
* on Windows, which lacks sigaction(), so we have to do it manually.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&BlockSig);
|
PG_SETMASK(&BlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
ereport(DEBUG2,
|
ereport(DEBUG2,
|
||||||
(errmsg_internal("postmaster received signal %d",
|
(errmsg_internal("postmaster received signal %d",
|
||||||
|
@ -2867,7 +2890,9 @@ pmdie(SIGNAL_ARGS)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&UnBlockSig);
|
PG_SETMASK(&UnBlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
@ -2882,7 +2907,13 @@ reaper(SIGNAL_ARGS)
|
||||||
int pid; /* process id of dead child process */
|
int pid; /* process id of dead child process */
|
||||||
int exitstatus; /* its exit status */
|
int exitstatus; /* its exit status */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We rely on the signal mechanism to have blocked all signals ... except
|
||||||
|
* on Windows, which lacks sigaction(), so we have to do it manually.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&BlockSig);
|
PG_SETMASK(&BlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
ereport(DEBUG4,
|
ereport(DEBUG4,
|
||||||
(errmsg_internal("reaping dead processes")));
|
(errmsg_internal("reaping dead processes")));
|
||||||
|
@ -3184,7 +3215,9 @@ reaper(SIGNAL_ARGS)
|
||||||
PostmasterStateMachine();
|
PostmasterStateMachine();
|
||||||
|
|
||||||
/* Done with signal handler */
|
/* Done with signal handler */
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&UnBlockSig);
|
PG_SETMASK(&UnBlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
@ -5086,7 +5119,13 @@ sigusr1_handler(SIGNAL_ARGS)
|
||||||
{
|
{
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We rely on the signal mechanism to have blocked all signals ... except
|
||||||
|
* on Windows, which lacks sigaction(), so we have to do it manually.
|
||||||
|
*/
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&BlockSig);
|
PG_SETMASK(&BlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Process background worker state change. */
|
/* Process background worker state change. */
|
||||||
if (CheckPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE))
|
if (CheckPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE))
|
||||||
|
@ -5244,7 +5283,9 @@ sigusr1_handler(SIGNAL_ARGS)
|
||||||
signal_child(StartupPID, SIGUSR2);
|
signal_child(StartupPID, SIGUSR2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
PG_SETMASK(&UnBlockSig);
|
PG_SETMASK(&UnBlockSig);
|
||||||
|
#endif
|
||||||
|
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,4 +36,7 @@ extern sigset_t UnBlockSig,
|
||||||
|
|
||||||
extern void pqinitmask(void);
|
extern void pqinitmask(void);
|
||||||
|
|
||||||
|
/* pqsigfunc is declared in src/include/port.h */
|
||||||
|
extern pqsigfunc pqsignal_pm(int signo, pqsigfunc func);
|
||||||
|
|
||||||
#endif /* PQSIGNAL_H */
|
#endif /* PQSIGNAL_H */
|
||||||
|
|
|
@ -524,11 +524,6 @@ extern int pg_mkdir_p(char *path, int omode);
|
||||||
/* port/pqsignal.c */
|
/* port/pqsignal.c */
|
||||||
typedef void (*pqsigfunc) (int signo);
|
typedef void (*pqsigfunc) (int signo);
|
||||||
extern pqsigfunc pqsignal(int signo, pqsigfunc func);
|
extern pqsigfunc pqsignal(int signo, pqsigfunc func);
|
||||||
#ifndef WIN32
|
|
||||||
extern pqsigfunc pqsignal_no_restart(int signo, pqsigfunc func);
|
|
||||||
#else
|
|
||||||
#define pqsignal_no_restart(signo, func) pqsignal(signo, func)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* port/quotes.c */
|
/* port/quotes.c */
|
||||||
extern char *escape_single_quotes_ascii(const char *src);
|
extern char *escape_single_quotes_ascii(const char *src);
|
||||||
|
|
|
@ -58,33 +58,4 @@ pqsignal(int signo, pqsigfunc func)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set up a signal handler, without SA_RESTART, for signal "signo"
|
|
||||||
*
|
|
||||||
* Returns the previous handler.
|
|
||||||
*
|
|
||||||
* On Windows, this would be identical to pqsignal(), so don't bother.
|
|
||||||
*/
|
|
||||||
#ifndef WIN32
|
|
||||||
|
|
||||||
pqsigfunc
|
|
||||||
pqsignal_no_restart(int signo, pqsigfunc func)
|
|
||||||
{
|
|
||||||
struct sigaction act,
|
|
||||||
oact;
|
|
||||||
|
|
||||||
act.sa_handler = func;
|
|
||||||
sigemptyset(&act.sa_mask);
|
|
||||||
act.sa_flags = 0;
|
|
||||||
#ifdef SA_NOCLDSTOP
|
|
||||||
if (signo == SIGCHLD)
|
|
||||||
act.sa_flags |= SA_NOCLDSTOP;
|
|
||||||
#endif
|
|
||||||
if (sigaction(signo, &act, &oact) < 0)
|
|
||||||
return SIG_ERR;
|
|
||||||
return oact.sa_handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !WIN32 */
|
|
||||||
|
|
||||||
#endif /* !defined(WIN32) || defined(FRONTEND) */
|
#endif /* !defined(WIN32) || defined(FRONTEND) */
|
||||||
|
|
Loading…
Reference in New Issue