From cc98002189e99be73fc8486f07752c3de03e5016 Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Thu, 25 Aug 2022 12:48:00 +0200 Subject: [PATCH 1/4] Handle memory allocation failures. This makes the code a little more robust. --- config.c | 4 ++++ config.h | 2 ++ restartd.c | 30 +++++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/config.c b/config.c index f307b8a..236ebf1 100644 --- a/config.c +++ b/config.c @@ -57,7 +57,11 @@ int read_config(void) config_process_number = 0; line1 = (char *) malloc(MAX_LINE_LENGTH); + if (!line1) + oom_failure(); line2 = (char *) malloc(MAX_LINE_LENGTH); + if (!line2) + oom_failure(); if ((config_fd = fopen(config_file, "rt")) == NULL) { fprintf(stderr, "Error at opening config file: %s\n", config_file); diff --git a/config.h b/config.h index fabaa2b..b5a134a 100644 --- a/config.h +++ b/config.h @@ -1,6 +1,7 @@ /* restartd - Process checker and/or restarter daemon * Copyright (C) 2000-2002 Tibor Koleszar * Copyright (C) 2006 Aurélien GÉRÔME + * Copyright (C) 2022 Maxime Devos * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,5 +44,6 @@ typedef struct config_process_type { int read_config(/* char *config_file */); void dump_config(void); +void oom_failure(void); #endif /* RESTARTD_CONFIG_H */ diff --git a/restartd.c b/restartd.c index 2aa720c..be00528 100644 --- a/restartd.c +++ b/restartd.c @@ -1,6 +1,7 @@ /* restartd - Process checker and/or restarter daemon * Copyright (C) 2000-2002 Tibor Koleszar * Copyright (C) 2006 Aurélien GÉRÔME + * Copyright (C) 2022 Maxime Devos * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -52,6 +53,17 @@ void got_signal(int sig) } } +/* Ignoring out-of-memory failures is risky on systems without virtual memory + where additionally at address 0 there is actually something important + mapped. Additionally, while often on Linux the OOM killer will kill processes + where an OOM happens, this is not always the case and there exist other systems + without an OOM killer (e.g. the Hurd). */ +void oom_failure() +{ + syslog(LOG_ERR, "Failed to allocate memory. Exiting."); + exit(1); +} + int main(int argc, char *argv[]) { DIR *procdir_id; @@ -75,15 +87,21 @@ int main(int argc, char *argv[]) /* Options */ config_file = strdup(DEFAULT_CONFIG); + if (!config_file) + oom_failure(); + list_only = 0; for(i = 0; i < argc; i++) { if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) { config_file = strdup(argv[i + 1]); + if (!config_file) + oom_failure(); } if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { printf("restard %s - Copyright 2000-2002 Tibor Koleszar \n" - " Copyright 2006 Aurélien GÉRÔME \n", + " Copyright 2006 Aurélien GÉRÔME \n" + " Copyright 2022 Maxime Devos \n", VERSION); exit(0); } @@ -122,6 +140,8 @@ int main(int argc, char *argv[]) } config_process = malloc(sizeof(struct config_process_type) * 128); + if (!config_process) + oom_failure(); read_config(); if (list_only) { @@ -133,9 +153,17 @@ int main(int argc, char *argv[]) config_process_number); procdir_dirent = malloc(sizeof(struct dirent)); + if (!procdir_dirent) + oom_failure(); proc_cmdline_str = (char *) malloc(1024); + if (!proc_cmdline_str) + oom_failure(); proc_cmdline_name = (char *) malloc(1024); + if (!proc_cmdline_name) + oom_failure(); regc = malloc(1024); + if (!regc) + oom_failure(); /* Catch signals */ signal(SIGTERM, got_signal); From 59fbc7a3e33071bb40e10f6723b7ff9c8628fada Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Thu, 25 Aug 2022 12:51:58 +0200 Subject: [PATCH 2/4] Handle fopen failures. This makes the code a little more robust. What if /var/run does not exist, or we do not have permission to open /var/run/restartd.pid (EPERM?) due to SELinux misconfiguration? --- restartd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/restartd.c b/restartd.c index be00528..48951f4 100644 --- a/restartd.c +++ b/restartd.c @@ -215,6 +215,10 @@ int main(int argc, char *argv[]) } out_proc = fopen("/var/run/restartd.pid", "wt"); + if (!out_proc) { + syslog(LOG_ERR, "Failed to open /var/run/restartd.pid"); + return -1; + } fprintf(out_proc, "%d", getpid()); fclose(out_proc); @@ -265,6 +269,10 @@ int main(int argc, char *argv[]) now = time(NULL); out_proc = fopen("/var/run/restartd", "wt"); + if (!out_proc) { + syslog(LOG_ERR, "Failed to open /var/run/restartd"); + return -1; + } fprintf(out_proc, "%s\n", ctime(&now)); From 70ce11fd3785675514e64a829e7e96446331eef0 Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Thu, 25 Aug 2022 13:02:23 +0200 Subject: [PATCH 3/4] Handle printf and fprintf failures. This makes the code a little more robust. What if the write was refused to the underlying device being removed? The --help, debug and stderr printfs were ignored because there error handling does not appear important to me. --- config.c | 15 ++++++++++----- restartd.c | 19 ++++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/config.c b/config.c index 236ebf1..94907e3 100644 --- a/config.c +++ b/config.c @@ -159,11 +159,16 @@ void dump_config(void) { int i; for(i=0; i 0) { @@ -303,9 +309,12 @@ int main(int argc, char *argv[]) strcpy(config_process[i].status, "not running"); } - fprintf(out_proc, "%-12s %-12s %s\n", - config_process[i].name, config_process[i].status, - config_process[i].processes); + if (fprintf(out_proc, "%-12s %-12s %s\n", + config_process[i].name, config_process[i].status, + config_process[i].processes) < 0) { + syslog(LOG_ERR, "Failed to write to /var/run/restartd. Exiting."); + return -1; + } } fclose(out_proc); From 4411ad32cd12f4836812807ffc102a1e7a2ecb8c Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Thu, 25 Aug 2022 13:07:08 +0200 Subject: [PATCH 4/4] Handle fclose failures when writing. This makes the code a little more robust. What if a quotum is exceeded? --- restartd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/restartd.c b/restartd.c index 229724d..4cacdef 100644 --- a/restartd.c +++ b/restartd.c @@ -223,7 +223,10 @@ int main(int argc, char *argv[]) syslog(LOG_ERR, "Failed to write to /var/run/restartd.pid. Exiting."); return -1; } - fclose(out_proc); + if (fclose(out_proc) < 0) { /* errors can happen when flushing the buffer */ + syslog(LOG_ERR, "Failed to write to /var/run/restartd.pid. Exiting."); + return -1; + } while(1) { if ((procdir_id = opendir("/proc")) == NULL) { @@ -317,7 +320,10 @@ int main(int argc, char *argv[]) } } - fclose(out_proc); + if (fclose(out_proc) < 0) { + syslog(LOG_ERR, "Failed to write to /var/run/restartd.pid. Exiting."); + return -1; + } sleep(check_interval); }