systemd-fsck: fix systemd-fsck/fsck pipe bad closure

Currently, when console is disabled but progress is tracked, pipe opened
for communication between systemd-fsck and fsck may be closed
inadvertently (when opening of /dev/console return in error). That lead
to finish fsck prematurely (because it receives a SIGPIPE) and so fsck
may not check correctly filesystems and do not have time to fix memory
corruptions.

This commit changes the opening of /dev/console to be done previously to
pipe creation and so fix the bug described just above.
This commit is contained in:
Benjamin Bouvier 2019-10-01 12:12:10 +03:00 committed by Zbigniew Jędrzejewski-Szmek
parent ab84cf9191
commit e4fc745547

View file

@ -156,8 +156,8 @@ static double percent(int pass, unsigned long cur, unsigned long max) {
(double) cur / (double) max;
}
static int process_progress(int fd) {
_cleanup_fclose_ FILE *console = NULL, *f = NULL;
static int process_progress(int fd, FILE* console) {
_cleanup_fclose_ FILE *f = NULL;
usec_t last = 0;
bool locked = false;
int clear = 0, r;
@ -172,10 +172,6 @@ static int process_progress(int fd) {
return log_debug_errno(errno, "Failed to use pipe: %m");
}
console = fopen("/dev/console", "we");
if (!console)
return log_debug_errno(errno, "Failed to open /dev/console, can't print progress output: %m");
for (;;) {
int pass, m;
unsigned long cur, max;
@ -254,6 +250,7 @@ static int run(int argc, char *argv[]) {
_cleanup_close_pair_ int progress_pipe[2] = { -1, -1 };
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
_cleanup_free_ char *dpath = NULL;
_cleanup_fclose_ FILE *console = NULL;
const char *device, *type;
bool root_directory;
struct stat st;
@ -342,7 +339,9 @@ static int run(int argc, char *argv[]) {
}
}
if (arg_show_progress &&
console = fopen("/dev/console", "we");
if (console &&
arg_show_progress &&
pipe(progress_pipe) < 0)
return log_error_errno(errno, "pipe(): %m");
@ -401,8 +400,10 @@ static int run(int argc, char *argv[]) {
_exit(FSCK_OPERATIONAL_ERROR);
}
progress_pipe[1] = safe_close(progress_pipe[1]);
(void) process_progress(TAKE_FD(progress_pipe[0]));
if (console) {
progress_pipe[1] = safe_close(progress_pipe[1]);
(void) process_progress(TAKE_FD(progress_pipe[0]), console);
}
exit_status = wait_for_terminate_and_check("fsck", pid, WAIT_LOG_ABNORMAL);
if (exit_status < 0)