!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);
|
||||
#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.
|
||||
*
|
||||
* In the postmaster, we want to install non-ignored handlers *without*
|
||||
* SA_RESTART. This is because they'll 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, but we expect them to
|
||||
* set up their own handlers before unblocking signals.
|
||||
* In the postmaster, we use pqsignal_pm() rather than pqsignal() (which
|
||||
* is used by all child processes and client processes). That has a
|
||||
* couple of special behaviors:
|
||||
*
|
||||
* 1. Except on Windows, we tell sigaction() to block all signals for the
|
||||
* duration of the signal handler. This is faster than our old approach
|
||||
* of blocking/unblocking explicitly in the signal handler, and it should
|
||||
* 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
|
||||
* handling setup of child processes. See tcop/postgres.c,
|
||||
|
@ -625,18 +636,16 @@ PostmasterMain(int argc, char *argv[])
|
|||
pqinitmask();
|
||||
PG_SETMASK(&BlockSig);
|
||||
|
||||
pqsignal_no_restart(SIGHUP, SIGHUP_handler); /* reread config file and
|
||||
* have children do same */
|
||||
pqsignal_no_restart(SIGINT, pmdie); /* send SIGTERM and shut down */
|
||||
pqsignal_no_restart(SIGQUIT, pmdie); /* send SIGQUIT and die */
|
||||
pqsignal_no_restart(SIGTERM, pmdie); /* wait for children and shut down */
|
||||
pqsignal(SIGALRM, SIG_IGN); /* ignored */
|
||||
pqsignal(SIGPIPE, SIG_IGN); /* ignored */
|
||||
pqsignal_no_restart(SIGUSR1, sigusr1_handler); /* message from child
|
||||
* process */
|
||||
pqsignal_no_restart(SIGUSR2, dummy_handler); /* unused, reserve for
|
||||
* children */
|
||||
pqsignal_no_restart(SIGCHLD, reaper); /* handle child termination */
|
||||
pqsignal_pm(SIGHUP, SIGHUP_handler); /* reread config file and have
|
||||
* children do same */
|
||||
pqsignal_pm(SIGINT, pmdie); /* send SIGTERM and shut down */
|
||||
pqsignal_pm(SIGQUIT, pmdie); /* send SIGQUIT and die */
|
||||
pqsignal_pm(SIGTERM, pmdie); /* wait for children and shut down */
|
||||
pqsignal_pm(SIGALRM, SIG_IGN); /* ignored */
|
||||
pqsignal_pm(SIGPIPE, SIG_IGN); /* ignored */
|
||||
pqsignal_pm(SIGUSR1, sigusr1_handler); /* message from child process */
|
||||
pqsignal_pm(SIGUSR2, dummy_handler); /* unused, reserve for children */
|
||||
pqsignal_pm(SIGCHLD, reaper); /* handle child termination */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#ifdef SIGTTIN
|
||||
pqsignal(SIGTTIN, SIG_IGN); /* ignored */
|
||||
pqsignal_pm(SIGTTIN, SIG_IGN); /* ignored */
|
||||
#endif
|
||||
#ifdef SIGTTOU
|
||||
pqsignal(SIGTTOU, SIG_IGN); /* ignored */
|
||||
pqsignal_pm(SIGTTOU, SIG_IGN); /* ignored */
|
||||
#endif
|
||||
|
||||
/* ignore SIGXFSZ, so that ulimit violations work like disk full */
|
||||
#ifdef SIGXFSZ
|
||||
pqsignal(SIGXFSZ, SIG_IGN); /* ignored */
|
||||
pqsignal_pm(SIGXFSZ, SIG_IGN); /* ignored */
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -2627,7 +2636,13 @@ SIGHUP_handler(SIGNAL_ARGS)
|
|||
{
|
||||
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);
|
||||
#endif
|
||||
|
||||
if (Shutdown <= SmartShutdown)
|
||||
{
|
||||
|
@ -2687,7 +2702,9 @@ SIGHUP_handler(SIGNAL_ARGS)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
PG_SETMASK(&UnBlockSig);
|
||||
#endif
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
|
@ -2701,7 +2718,13 @@ pmdie(SIGNAL_ARGS)
|
|||
{
|
||||
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);
|
||||
#endif
|
||||
|
||||
ereport(DEBUG2,
|
||||
(errmsg_internal("postmaster received signal %d",
|
||||
|
@ -2867,7 +2890,9 @@ pmdie(SIGNAL_ARGS)
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
PG_SETMASK(&UnBlockSig);
|
||||
#endif
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
|
@ -2882,7 +2907,13 @@ reaper(SIGNAL_ARGS)
|
|||
int pid; /* process id of dead child process */
|
||||
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);
|
||||
#endif
|
||||
|
||||
ereport(DEBUG4,
|
||||
(errmsg_internal("reaping dead processes")));
|
||||
|
@ -3184,7 +3215,9 @@ reaper(SIGNAL_ARGS)
|
|||
PostmasterStateMachine();
|
||||
|
||||
/* Done with signal handler */
|
||||
#ifdef WIN32
|
||||
PG_SETMASK(&UnBlockSig);
|
||||
#endif
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
|
@ -5086,7 +5119,13 @@ sigusr1_handler(SIGNAL_ARGS)
|
|||
{
|
||||
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);
|
||||
#endif
|
||||
|
||||
/* Process background worker state change. */
|
||||
if (CheckPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE))
|
||||
|
@ -5244,7 +5283,9 @@ sigusr1_handler(SIGNAL_ARGS)
|
|||
signal_child(StartupPID, SIGUSR2);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
PG_SETMASK(&UnBlockSig);
|
||||
#endif
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
|
|
|
@ -36,4 +36,7 @@ extern sigset_t UnBlockSig,
|
|||
|
||||
extern void pqinitmask(void);
|
||||
|
||||
/* pqsigfunc is declared in src/include/port.h */
|
||||
extern pqsigfunc pqsignal_pm(int signo, pqsigfunc func);
|
||||
|
||||
#endif /* PQSIGNAL_H */
|
||||
|
|
|
@ -524,11 +524,6 @@ extern int pg_mkdir_p(char *path, int omode);
|
|||
/* port/pqsignal.c */
|
||||
typedef void (*pqsigfunc) (int signo);
|
||||
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 */
|
||||
extern char *escape_single_quotes_ascii(const char *src);
|
||||
|
|
|
@ -58,33 +58,4 @@ pqsignal(int signo, pqsigfunc func)
|
|||
#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) */
|
||||
|
|
Loading…
Reference in New Issue