Added new signal handler for SIGUSR2. When init receives SIGUSR2

it closes (and leaves closed) the named pipe /run/initctl. This
can be used to make sure init does not have any files open. However,
it also means we cannot switch run levels or bring down the system.
The pipe can be re-opened by sending init the SIGUSR1 signal.

Updated the man pages for initctl and init to include this information.
This commit is contained in:
Jesse Smith 2018-04-17 19:44:50 -03:00
parent f09da9cb55
commit 272f112c98
4 changed files with 43 additions and 4 deletions

View File

@ -18,6 +18,11 @@ sysvinit (2.90) UNRELEASED; urgency=low
* Added check that named pipe is open before trying to close it * Added check that named pipe is open before trying to close it
when something goes wrong or we receive SIGUSER1. Avoids potential when something goes wrong or we receive SIGUSER1. Avoids potential
crash if we receive SIGUSR1 while pipe is not open. crash if we receive SIGUSR1 while pipe is not open.
* Added new signal handler for SIGUSR2. When init receives SIGUSR2
it closes (and leaves closed) the named pipe /run/initctl. This
can be used to make sure init does not have any files open. However,
it also means we cannot switch run levels or bring down the system.
The pipe can be re-opened by sending init the SIGUSR1 signal.
sysvinit (2.89) world; urgency=low sysvinit (2.89) world; urgency=low

View File

@ -264,6 +264,13 @@ Has the same effect as \fBtelinit q\fP.
On receipt of this signals, init closes and re-opens its control fifo, On receipt of this signals, init closes and re-opens its control fifo,
\fB/run/initctl\fP. Useful for bootscripts when /dev is remounted. \fB/run/initctl\fP. Useful for bootscripts when /dev is remounted.
.TP 0.5i .TP 0.5i
.B SIGUSR2
When init receives SIGUSR2, init closes and leaves the control fifo,
\fB/run/initctl\f\P, closed. This may be used to make sure init is not
holding open any files. However, it also prevents init from switching
runlevels. Which means commands like shutdown no longer work.
The fifo can be re-opened by sending init the SIGUSR1 signal.
.TP 0.5i
.B SIGINT .B SIGINT
Normally the kernel sends this signal to init when CTRL-ALT-DEL is Normally the kernel sends this signal to init when CTRL-ALT-DEL is
pressed. It activates the \fIctrlaltdel\fP action. pressed. It activates the \fIctrlaltdel\fP action.

View File

@ -128,6 +128,18 @@ The commands passed through the /run/initctl pipe must be sent in a specific
binary format and be of a specific length. Larger data structures or ones binary format and be of a specific length. Larger data structures or ones
not using the proper format will be ignored. Typically, only root has the not using the proper format will be ignored. Typically, only root has the
ability to write to the initctl pipe for security reasons. ability to write to the initctl pipe for security reasons.
.PP
The /run/initctl pipe can be closed by sending init (PID 1) the SIGUSR2
signal. This closes the pipe and leaves it closed. This may be useful
for making sure init is not keeping any files open. However, when the
pipe is closed, init no longer receives signals, such as those sent by
shutdown or telinit. In other words if we close the pipe, init cannot
change its runlevel directly. The pipe may be re-opened by sending init (PID 1)
the SIGUSR1 signal.
.PP
If the /run/initctl pipe is closed then it may still be possible to bring
down the system using the shutdown command's -n flag, but this is not
always clean and not recommended.
.RE .RE
.SH FILES .SH FILES
/run/initctl /run/initctl

View File

@ -1116,7 +1116,11 @@ pid_t spawn(CHILD *ch, int *res)
close(0); close(0);
close(1); close(1);
close(2); close(2);
if (pipe_fd >= 0) close(pipe_fd); if (pipe_fd >= 0)
{
close(pipe_fd);
pipe_fd = -1;
}
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
@ -2172,6 +2176,7 @@ void re_exec(void)
DELSET(got_signals, SIGCHLD); DELSET(got_signals, SIGCHLD);
DELSET(got_signals, SIGHUP); DELSET(got_signals, SIGHUP);
DELSET(got_signals, SIGUSR1); DELSET(got_signals, SIGUSR1);
DELSET(got_signals, SIGUSR2);
/* /*
* That should be cleaned. * That should be cleaned.
@ -2368,9 +2373,10 @@ void check_init_fifo(void)
} }
/* /*
* Now finally try to open /run/initctl * Now finally try to open /run/initctl if pipe_fd is -1
* if it is -2, then we leave it closed
*/ */
if (pipe_fd < 0) { if (pipe_fd == -1) {
if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) { if ((pipe_fd = open(INIT_FIFO, O_RDWR|O_NONBLOCK)) >= 0) {
fstat(pipe_fd, &st); fstat(pipe_fd, &st);
if (!S_ISFIFO(st.st_mode)) { if (!S_ISFIFO(st.st_mode)) {
@ -2471,7 +2477,7 @@ void check_init_fifo(void)
/* /*
* We come here if the pipe couldn't be opened. * We come here if the pipe couldn't be opened.
*/ */
if (pipe_fd < 0) pause(); if (pipe_fd == -1) pause();
} }
@ -2682,6 +2688,14 @@ void process_signals()
pipe_fd = -1; pipe_fd = -1;
DELSET(got_signals, SIGUSR1); DELSET(got_signals, SIGUSR1);
} }
else if (ISMEMBER(got_signals, SIGUSR2)) {
/* SIGUSR1 mean close the pipe and leave it closed */
INITDBG(L_VB, "got SIGUSR2");
if (pipe_fd)
close(pipe_fd);
pipe_fd = -2;
DELSET(got_signals, SIGUSR2);
}
} }
/* /*
@ -2740,6 +2754,7 @@ void init_main(void)
SETSIG(sa, SIGPWR, signal_handler, 0); SETSIG(sa, SIGPWR, signal_handler, 0);
SETSIG(sa, SIGWINCH, signal_handler, 0); SETSIG(sa, SIGWINCH, signal_handler, 0);
SETSIG(sa, SIGUSR1, signal_handler, 0); SETSIG(sa, SIGUSR1, signal_handler, 0);
SETSIG(sa, SIGUSR2, signal_handler, 0);
SETSIG(sa, SIGSTOP, stop_handler, SA_RESTART); SETSIG(sa, SIGSTOP, stop_handler, SA_RESTART);
SETSIG(sa, SIGTSTP, stop_handler, SA_RESTART); SETSIG(sa, SIGTSTP, stop_handler, SA_RESTART);
SETSIG(sa, SIGCONT, cont_handler, SA_RESTART); SETSIG(sa, SIGCONT, cont_handler, SA_RESTART);