* gnu/packages/admin.scm (restartd): New variable. * gnu/packages/patches/restartd-update-robust.patch: Add file. * gnu/local.mk: Register gnu/packages/patches/restartd-update-robust.patch. Change-Id: I38b9b70e97b64f006a86d7618a75f1ec3ed8b034 Signed-off-by: Ludovic Courtès <ludo@gnu.org>
		
			
				
	
	
		
			295 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 01cd2d15a9bf1109e0e71b3e31b835d63dcf9cd8 Mon Sep 17 00:00:00 2001
 | 
						|
From: Maxime Devos <maximedevos@telenet.be>, Yin Kangkai <yinkangkai@xiaomi.com>, Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 | 
						|
Subject: [PATCH]
 | 
						|
 | 
						|
Fix segfault when run as normal user
 | 
						|
 | 
						|
Also exit immediately when "restartd -h"
 | 
						|
Signed-off-by: Yin Kangkai <yinkangkai@xiaomi.com>
 | 
						|
 | 
						|
Fix build with gcc-10
 | 
						|
 | 
						|
Bug: https://bugs.debian.org/957761
 | 
						|
Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 | 
						|
 | 
						|
Handle memory allocation failures.
 | 
						|
 | 
						|
This makes the code a little more robust.
 | 
						|
Signed-off-by: Maxime Devos <maximedevos@telenet.be>
 | 
						|
 | 
						|
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?
 | 
						|
Signed-off-by: Maxime Devos <maximedevos@telenet.be>
 | 
						|
 | 
						|
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.
 | 
						|
Signed-off-by: Maxime Devos <maximedevos@telenet.be>
 | 
						|
 | 
						|
Handle fclose failures when writing.
 | 
						|
 | 
						|
This makes the code a little more robust. What if a quotum is exceeded?
 | 
						|
Signed-off-by: Maxime Devos <maximedevos@telenet.be>
 | 
						|
---
 | 
						|
 config.c   | 19 +++++++++----
 | 
						|
 config.h   | 14 ++++++----
 | 
						|
 restartd.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-------
 | 
						|
 3 files changed, 92 insertions(+), 21 deletions(-)
 | 
						|
 | 
						|
diff --git a/config.c b/config.c
 | 
						|
index f307b8a..5cc0271 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);
 | 
						|
@@ -155,11 +159,16 @@ void dump_config(void) {
 | 
						|
     int i;
 | 
						|
 
 | 
						|
     for(i=0; i<config_process_number; i++) {
 | 
						|
-        printf("ID=%d\n  name=%s\n  regexp=%s\n  running=%s\n  not_running=%s\n", i,
 | 
						|
-            config_process[i].name,
 | 
						|
-            config_process[i].regexp,
 | 
						|
-            config_process[i].running,
 | 
						|
-            config_process[i].not_running);
 | 
						|
+      if (printf("ID=%d\n  name=%s\n  regexp=%s\n  running=%s\n  not_running=%s\n", i,
 | 
						|
+                 config_process[i].name,
 | 
						|
+                 config_process[i].regexp,
 | 
						|
+                 config_process[i].running,
 | 
						|
+                 config_process[i].not_running) < 0) {
 | 
						|
+        /* Maybe stdout points to a file and a file system quotum was exceeded? */
 | 
						|
+        fprintf(stderr, "Failed to dump the configuration. Exiting.\n");
 | 
						|
+        syslog(LOG_ERR, "Failed to dump the configuration. Exiting.");
 | 
						|
+        exit(1);
 | 
						|
+      }
 | 
						|
     }
 | 
						|
 
 | 
						|
 }
 | 
						|
diff --git a/config.h b/config.h
 | 
						|
index fabaa2b..2ba1cbe 100644
 | 
						|
--- a/config.h
 | 
						|
+++ b/config.h
 | 
						|
@@ -1,6 +1,7 @@
 | 
						|
 /* restartd - Process checker and/or restarter daemon
 | 
						|
  * Copyright (C) 2000-2002 Tibor Koleszar <oldw@debian.org>
 | 
						|
  * Copyright (C) 2006 Aurélien GÉRÔME <ag@roxor.cx>
 | 
						|
+ * Copyright (C) 2022 Maxime Devos <maximedevos@telenet.be>
 | 
						|
  *
 | 
						|
  * This program is free software; you can redistribute it and/or
 | 
						|
  * modify it under the terms of the GNU General Public License
 | 
						|
@@ -25,12 +26,12 @@
 | 
						|
 
 | 
						|
 #define DEFAULT_CONFIG "/etc/restartd.conf"
 | 
						|
 
 | 
						|
-int debug;
 | 
						|
-int config_process_number;
 | 
						|
-int check_interval;
 | 
						|
-int foreground;
 | 
						|
-struct config_process_type *config_process;
 | 
						|
-char *config_file;
 | 
						|
+extern int debug;
 | 
						|
+extern int config_process_number;
 | 
						|
+extern int check_interval;
 | 
						|
+extern int foreground;
 | 
						|
+extern struct config_process_type *config_process;
 | 
						|
+extern char *config_file;
 | 
						|
 
 | 
						|
 typedef struct config_process_type {
 | 
						|
   char name[64];
 | 
						|
@@ -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..aa74334 100644
 | 
						|
--- a/restartd.c
 | 
						|
+++ b/restartd.c
 | 
						|
@@ -1,6 +1,7 @@
 | 
						|
 /* restartd - Process checker and/or restarter daemon
 | 
						|
  * Copyright (C) 2000-2002 Tibor Koleszar <oldw@debian.org>
 | 
						|
  * Copyright (C) 2006 Aurélien GÉRÔME <ag@roxor.cx>
 | 
						|
+ * Copyright (C) 2022 Maxime Devos <maximedevos@telenet.be>
 | 
						|
  *
 | 
						|
  * This program is free software; you can redistribute it and/or
 | 
						|
  * modify it under the terms of the GNU General Public License
 | 
						|
@@ -35,6 +36,13 @@
 | 
						|
 
 | 
						|
 #include "config.h"
 | 
						|
 
 | 
						|
+int debug;
 | 
						|
+int config_process_number;
 | 
						|
+int check_interval;
 | 
						|
+int foreground;
 | 
						|
+struct config_process_type *config_process;
 | 
						|
+char *config_file;
 | 
						|
+
 | 
						|
 /* SIGTERM & SIGHUP handler */
 | 
						|
 void got_signal(int sig)
 | 
						|
 {
 | 
						|
@@ -52,6 +60,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 +94,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 <oldw@debian.org>\n"
 | 
						|
-                   "                Copyright 2006 Aurélien GÉRÔME <ag@roxor.cx>\n",
 | 
						|
+                   "                Copyright 2006 Aurélien GÉRÔME <ag@roxor.cx>\n"
 | 
						|
+                   "                Copyright 2022 Maxime Devos <maximedevos@telenet.be>\n",
 | 
						|
                    VERSION);
 | 
						|
             exit(0);
 | 
						|
         }
 | 
						|
@@ -118,10 +143,13 @@ int main(int argc, char *argv[])
 | 
						|
                     "  -i <interval_sec>: the check interval in second\n"
 | 
						|
                     "  -l               : list configuration options\n"
 | 
						|
                     "  -h               : help\n\n", VERSION);
 | 
						|
+	    exit(0);
 | 
						|
         }
 | 
						|
     }
 | 
						|
 
 | 
						|
     config_process = malloc(sizeof(struct config_process_type) * 128);
 | 
						|
+    if (!config_process)
 | 
						|
+      oom_failure();
 | 
						|
   
 | 
						|
     read_config();
 | 
						|
     if (list_only) {
 | 
						|
@@ -133,9 +161,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);
 | 
						|
@@ -187,8 +223,19 @@ int main(int argc, char *argv[])
 | 
						|
         }
 | 
						|
 
 | 
						|
         out_proc = fopen("/var/run/restartd.pid", "wt");
 | 
						|
-        fprintf(out_proc, "%d", getpid());
 | 
						|
-        fclose(out_proc);
 | 
						|
+	if (!out_proc) {
 | 
						|
+		syslog(LOG_ERR, "Failed to open /var/run/restartd.pid");
 | 
						|
+		return -1;
 | 
						|
+	}
 | 
						|
+        if (fprintf(out_proc, "%d", getpid()) < 0) {
 | 
						|
+          syslog(LOG_ERR, "Failed to write to /var/run/restartd.pid. Exiting.");
 | 
						|
+          return -1;
 | 
						|
+        }
 | 
						|
+        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) {
 | 
						|
@@ -237,16 +284,23 @@ 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.pid");
 | 
						|
+             return -1;
 | 
						|
+           }
 | 
						|
 
 | 
						|
-           fprintf(out_proc, "%s\n", ctime(&now));
 | 
						|
+           if (fprintf(out_proc, "%s\n", ctime(&now)) < 0) {
 | 
						|
+             syslog(LOG_ERR, "Failed to write to /var/run/restartd. Exiting.");
 | 
						|
+             return -1;
 | 
						|
+           }
 | 
						|
 
 | 
						|
            for(i=0; i<config_process_number; i++) {
 | 
						|
                if (strlen(config_process[i].processes) > 0) {
 | 
						|
                    if (strlen(config_process[i].running) > 0) {
 | 
						|
                        strcpy(config_process[i].status, "running");
 | 
						|
-                       syslog(LOG_INFO, "%s is running, executing '%s'",
 | 
						|
+                       /* syslog(LOG_INFO, "%s is running, executing '%s'",
 | 
						|
                               config_process[i].name,
 | 
						|
-                              config_process[i].running);
 | 
						|
+                              config_process[i].running); */
 | 
						|
                        system(config_process[i].running);
 | 
						|
                     } else {
 | 
						|
                         strcpy(config_process[i].status, "running");
 | 
						|
@@ -267,12 +321,18 @@ 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);
 | 
						|
+            if (fclose(out_proc) < 0) {
 | 
						|
+              syslog(LOG_ERR, "Failed to write to /var/run/restartd.pid. Exiting.");
 | 
						|
+              return -1;
 | 
						|
+            }
 | 
						|
 
 | 
						|
             sleep(check_interval);
 | 
						|
         }
 | 
						|
-- 
 | 
						|
2.37.3
 | 
						|
 |