Hi,

I've found that upsdrvctl crashes when there is not ports= specified ups.conf

#0  __strrchr_sse2 () at ../sysdeps/x86_64/strrchr.S:33
#1  xbasename (file=0x0) at common.c:266
#2  stop_driver (ups=0x1e163e0) at upsdrvctl.c:135
#3  send_all_drivers (command=0x4020f0 <stop_driver>) at upsdrvctl.c:446
#4  main (argc=1, argv=0x7ffff30be9c0) at upsdrvctl.c:565



 stop_driver (ups=0x1e163e0) at upsdrvctl.c:135:
        if (ret != 0) {
                snprintf(pidfn, sizeof(pidfn), "%s/%s-%s.pid", altpidpath(),
                        ups->driver, xbasename(ups->port));
                ret = stat(pidfn, &fs);
        }

ups->port is NULL which makes xbasename(NULL) crash. Seems this is the only 
problem with wrong configuration. During quick testing I did not find any other 
sensitive place or value.

How to reproduce this crash:
1)add ups to ups.conf, omit port configuration
2)run upsdrvctl stop


There is nothing checking ups configuration is ok for upsdrvctl. For daemon 
there is check in server/conf.c upsconf_add. I've moved that checking code to 
separate function upsconf.c : validate_upsconf and used this function from 
upsconf_add and from upsdrvctl.c , this was more intrusive than it seemed. See 
attached patch (tested). Simpler way would be just adding validate_upsconf to 
upsdrvctl.c but it'd lead to code duplication. Any comments?

Michal
Index: include/upsconf.h
===================================================================
--- include/upsconf.h	(revision 2479)
+++ include/upsconf.h	(working copy)
@@ -3,5 +3,18 @@
    
 /* open the ups.conf, parse it, and call back do_upsconf_args() */
 void read_upsconf(void);
-   
 
+/* remove invalid UPS configurations from upstable */
+void validate_upsconf(void);
+
+typedef struct ups_s {
+	char	*upsname;
+	char	*driver;
+	char	*port;
+	char	*desc;
+	int	sdorder;
+	int	maxstartdelay;
+	struct ups_s	*next;
+} ups_t;
+
+extern ups_t * upstable;
\ No newline at end of file
Index: common/upsconf.c
===================================================================
--- common/upsconf.c	(revision 2479)
+++ common/upsconf.c	(working copy)
@@ -26,7 +26,8 @@
 #include "common.h"
 #include "parseconf.h"
 
-	static	char	*ups_section;
+static	char	*ups_section;
+ups_t *upstable;
 
 /* handle arguments separated by parseconf */
 static void conf_args(int numargs, char **arg)
@@ -105,3 +106,48 @@
 
 	free(ups_section);
 }
+
+/* remove invalid UPS configurations from upstable */
+void validate_upsconf(void)
+{
+	ups_t	*tmp = upstable, *next, *old = NULL;
+	upstable = NULL;
+
+	if (!tmp) {
+		upslogx(LOG_WARNING, "Warning: no UPS definitions in ups.conf");
+		return;
+	}
+
+	while (tmp) {
+
+		/* save for later, since we delete as we go along */
+		next = tmp->next;
+
+		/* this should always be set, but better safe than sorry */
+		if (!tmp->upsname) {
+			tmp = tmp->next;
+			continue;
+		}
+
+		/* don't accept an entry that's missing items */
+		if ((!tmp->driver) || (!tmp->port)) {
+			upslogx(LOG_WARNING, "Warning: ignoring incomplete configuration for UPS [%s]\n", 
+				tmp->upsname);
+
+			/* free tmp's resources */
+			free(tmp->driver);
+			free(tmp->port);
+			free(tmp->desc);
+			free(tmp->upsname);
+			free(tmp);
+
+			if (old) 
+				old->next = next;
+		} else if (!old) {
+			upstable = old = tmp;
+		}
+
+		tmp = next;
+	}
+}
+
Index: server/conf.c
===================================================================
--- server/conf.c	(revision 2479)
+++ server/conf.c	(working copy)
@@ -319,40 +319,26 @@
 /* add valid UPSes from ups.conf to the internal structures */
 void upsconf_add(int reloading)
 {
-	ups_t	*tmp = upstable, *next;
+	ups_t	*tmp, *next;
 	char	statefn[SMALLBUF];
 
-	if (!tmp) {
-		upslogx(LOG_WARNING, "Warning: no UPS definitions in ups.conf");
-		return;
-	}
+	validate_upsconf();
+	tmp = upstable;
 
 	while (tmp) {
 
 		/* save for later, since we delete as we go along */
 		next = tmp->next;
 
-		/* this should always be set, but better safe than sorry */
-		if (!tmp->upsname) {
-			tmp = tmp->next;
-			continue;
-		}
+		snprintf(statefn, sizeof(statefn), "%s-%s",
+			tmp->driver, tmp->upsname);
 
-		/* don't accept an entry that's missing items */
-		if ((!tmp->driver) || (!tmp->port)) {
-			upslogx(LOG_WARNING, "Warning: ignoring incomplete configuration for UPS [%s]\n", 
-				tmp->upsname);
-		} else {
-			snprintf(statefn, sizeof(statefn), "%s-%s",
-				tmp->driver, tmp->upsname);
+		/* if a UPS exists, update it, else add it as new */
+		if ((reloading) && (get_ups_ptr(tmp->upsname) != NULL))
+			ups_update(statefn, tmp->upsname, tmp->desc);
+		else
+			ups_create(statefn, tmp->upsname, tmp->desc);
 
-			/* if a UPS exists, update it, else add it as new */
-			if ((reloading) && (get_ups_ptr(tmp->upsname) != NULL))
-				ups_update(statefn, tmp->upsname, tmp->desc);
-			else
-				ups_create(statefn, tmp->upsname, tmp->desc);
-		}
-
 		/* free tmp's resources */
 
 		free(tmp->driver);
Index: server/conf.h
===================================================================
--- server/conf.h	(revision 2479)
+++ server/conf.h	(working copy)
@@ -28,14 +28,6 @@
 /* flush existing config, then reread everything */
 void conf_reload(void);
 
-typedef struct ups_s {
-	char	*upsname;
-	char	*driver;
-	char	*port;
-	char	*desc;
-	struct ups_s	*next;
-} ups_t;
-
 /* used for really clean shutdowns */
 void delete_acls(void);
 void delete_access(void);
Index: drivers/upsdrvctl.c
===================================================================
--- drivers/upsdrvctl.c	(revision 2479)
+++ drivers/upsdrvctl.c	(working copy)
@@ -29,17 +29,6 @@
 #include "common.h"
 #include "upsconf.h"
 
-typedef struct {
-	char	*upsname;
-	char	*driver;
-	char	*port;
-	int	sdorder;
-	int	maxstartdelay;
-	void	*next;
-}	ups_t;
-
-static	ups_t	*upstable = NULL;
-
 static	int	maxsdorder = 0, testmode = 0, exec_error = 0;
 
 	/* timer - keeps us from getting stuck if a driver hangs */
@@ -101,6 +90,7 @@
 	tmp = xmalloc(sizeof(ups_t));
 	tmp->upsname = xstrdup(upsname);
 	tmp->driver = NULL;
+	tmp->desc = NULL;
 	tmp->port = NULL;
 	tmp->next = NULL;
 	tmp->sdorder = 0;
@@ -404,6 +394,7 @@
 		free(tmp->driver);
 		free(tmp->port);
 		free(tmp->upsname);
+		free(tmp->desc);
 		free(tmp);
 
 		tmp = next;
@@ -489,6 +480,7 @@
 	atexit(exit_cleanup);
 
 	read_upsconf();
+	validate_upsconf();
 
 	if (argc == 1)
 		send_all_drivers(command);
_______________________________________________
Nut-upsdev mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev

Reply via email to