1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-10-27 01:55:10 +03:00

signals: fix SIGINT blocking flaw causing inconsistent metadata

SIGINT isn't blocked properly after a sigint_allow(),
sigint_restore() cycle leading to illicit interruptable
metadata updates.  These can leave corrupted metadata behind.

Issues addressed in this commit:

sigint_allow() fails to set _oldmasked[] members properly due
to an offset by one bug on indexing the members of the array.

It bails out prematurely comparing to MAX_SIGINTS causing nesting
depths to be one less than MAX_SIGINTS.  Fix the comparision.

Correct the related comparison flaw in sigint_restore().

Initialize all sig_atomic_t variables consequently.

Resolves: rhbz1440766
This commit is contained in:
Heinz Mauelshagen 2017-04-10 18:16:09 +02:00
parent ef3e1013aa
commit 9a689fb8f0

View File

@ -22,7 +22,7 @@
static sigset_t _oldset; static sigset_t _oldset;
static int _signals_blocked = 0; static int _signals_blocked = 0;
static volatile sig_atomic_t _sigint_caught = 0; static volatile sig_atomic_t _sigint_caught = 0;
static volatile sig_atomic_t _handler_installed; static volatile sig_atomic_t _handler_installed = 0;
/* Support 3 level nesting, increase if needed more */ /* Support 3 level nesting, increase if needed more */
#define MAX_SIGINTS 3 #define MAX_SIGINTS 3
@ -67,7 +67,7 @@ void sigint_allow(void)
* Do not overwrite the backed-up handler data - * Do not overwrite the backed-up handler data -
* just increase nesting count. * just increase nesting count.
*/ */
if (++_handler_installed >= MAX_SIGINTS) if (++_handler_installed > MAX_SIGINTS)
return; return;
/* Grab old sigaction for SIGINT: shall not fail. */ /* Grab old sigaction for SIGINT: shall not fail. */
@ -85,7 +85,7 @@ void sigint_allow(void)
if (sigprocmask(0, NULL, &sigs)) if (sigprocmask(0, NULL, &sigs))
log_sys_debug("sigprocmask", ""); log_sys_debug("sigprocmask", "");
if ((_oldmasked[_handler_installed] = sigismember(&sigs, SIGINT))) { if ((_oldmasked[_handler_installed - 1] = sigismember(&sigs, SIGINT))) {
sigdelset(&sigs, SIGINT); sigdelset(&sigs, SIGINT);
if (sigprocmask(SIG_SETMASK, &sigs, NULL)) if (sigprocmask(SIG_SETMASK, &sigs, NULL))
log_sys_debug("sigprocmask", "SIG_SETMASK"); log_sys_debug("sigprocmask", "SIG_SETMASK");
@ -98,7 +98,7 @@ void sigint_restore(void)
return; return;
if (!_handler_installed || if (!_handler_installed ||
--_handler_installed >= MAX_SIGINTS) --_handler_installed > MAX_SIGINTS)
return; return;
/* Nesting count went below MAX_SIGINTS. */ /* Nesting count went below MAX_SIGINTS. */