Zdenek Prikryl 14baa0
--- acpid.8	2009/02/10 23:57:07	1.19
Zdenek Prikryl 14baa0
+++ acpid.8	2009/04/22 18:22:27	1.20
Zdenek Prikryl 14baa0
@@ -60,6 +60,10 @@
Zdenek Prikryl 14baa0
 This option changes the directory in which \fBacpid\fP looks for rule
Zdenek Prikryl 14baa0
 configuration files.  Default is \fI/etc/acpi/events\fP.
Zdenek Prikryl 14baa0
 .TP 12
Zdenek Prikryl 14baa0
+.BI \-C "\fR, \fP" \--clientmax " number"
Zdenek Prikryl 14baa0
+This option changes the maximum number of non-root socket connections which
Zdenek Prikryl 14baa0
+can be made to the \fBacpid\fP socket.  Default is \fI256\fP.
Zdenek Prikryl 14baa0
+.TP 12
Zdenek Prikryl 14baa0
 .BI \-d "\fR, \fP" \--debug
Zdenek Prikryl 14baa0
 This option increases the \fBacpid\fP debug level by one.  If the debug level
Zdenek Prikryl 14baa0
 is non-zero, \fBacpid\fP will run in the foreground, and will log to
Zdenek Prikryl 14baa0
--- acpid.c	2009/02/18 17:35:25	1.31
Zdenek Prikryl 14baa0
+++ acpid.c	2009/04/22 18:22:28	1.32
Zdenek Prikryl 14baa0
@@ -44,6 +44,7 @@
Zdenek Prikryl 14baa0
 static int open_log(void);
Zdenek Prikryl 14baa0
 static int create_pidfile(void);
Zdenek Prikryl 14baa0
 static void clean_exit(int sig);
Zdenek Prikryl 14baa0
+static void clean_exit_with_status(int status);
Zdenek Prikryl 14baa0
 static void reload_conf(int sig);
Zdenek Prikryl 14baa0
 static char *read_line(int fd);
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
@@ -53,6 +54,9 @@
Zdenek Prikryl 14baa0
 /* do we log event info? */
Zdenek Prikryl 14baa0
 int logevents;
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
+/* the number of non-root clients that are connected */
Zdenek Prikryl 14baa0
+int non_root_clients;
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
 static const char *progname;
Zdenek Prikryl 14baa0
 static const char *confdir = ACPID_CONFDIR;
Zdenek Prikryl 14baa0
 static const char *eventfile = ACPID_EVENTFILE;
Zdenek Prikryl 14baa0
@@ -63,6 +67,7 @@
Zdenek Prikryl 14baa0
 static mode_t socketmode = ACPID_SOCKETMODE;
Zdenek Prikryl 14baa0
 static int foreground;
Zdenek Prikryl 14baa0
 static const char *pidfile = ACPID_PIDFILE;
Zdenek Prikryl 14baa0
+static int clientmax = ACPID_CLIENTMAX;
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 int
Zdenek Prikryl 14baa0
 main(int argc, char **argv)
Zdenek Prikryl 14baa0
@@ -190,7 +195,7 @@
Zdenek Prikryl 14baa0
 		struct pollfd ar[2];
Zdenek Prikryl 14baa0
 		int r;
Zdenek Prikryl 14baa0
 		int fds = 0;
Zdenek Prikryl 14baa0
-		
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
 		/* poll for the socket and the event file */
Zdenek Prikryl 14baa0
 		ar[0].fd = event_fd; ar[0].events = POLLIN; fds++;
Zdenek Prikryl 14baa0
 		if (!nosocket) {
Zdenek Prikryl 14baa0
@@ -205,6 +210,9 @@
Zdenek Prikryl 14baa0
 			continue;
Zdenek Prikryl 14baa0
 		}
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
+		/* house keeping */
Zdenek Prikryl 14baa0
+		acpid_close_dead_clients();
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
 		/* was it an event? */
Zdenek Prikryl 14baa0
 		if (ar[0].revents) {
Zdenek Prikryl 14baa0
 			char *event;
Zdenek Prikryl 14baa0
@@ -259,13 +267,14 @@
Zdenek Prikryl 14baa0
 					break;
Zdenek Prikryl 14baa0
 				}
Zdenek Prikryl 14baa0
 			}
Zdenek Prikryl 14baa0
-		} 
Zdenek Prikryl 14baa0
+		}
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 		/* was it a new connection? */
Zdenek Prikryl 14baa0
 		if (!nosocket && ar[1].revents) {
Zdenek Prikryl 14baa0
 			int cli_fd;
Zdenek Prikryl 14baa0
 			struct ucred creds;
Zdenek Prikryl 14baa0
 			char buf[32];
Zdenek Prikryl 14baa0
+			static int accept_errors;
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 			/* this shouldn't happen */
Zdenek Prikryl 14baa0
 			if (!ar[1].revents & POLLIN) {
Zdenek Prikryl 14baa0
@@ -280,8 +289,23 @@
Zdenek Prikryl 14baa0
 			if (cli_fd < 0) {
Zdenek Prikryl 14baa0
 				acpid_log(LOG_ERR, "can't accept client: %s\n",
Zdenek Prikryl 14baa0
 				    strerror(errno));
Zdenek Prikryl 14baa0
+				accept_errors++;
Zdenek Prikryl 14baa0
+				if (accept_errors >= 5) {
Zdenek Prikryl 14baa0
+					acpid_log(LOG_ERR, "giving up\n");
Zdenek Prikryl 14baa0
+					clean_exit_with_status(EXIT_FAILURE);
Zdenek Prikryl 14baa0
+				}
Zdenek Prikryl 14baa0
+				continue;
Zdenek Prikryl 14baa0
+			}
Zdenek Prikryl 14baa0
+			accept_errors = 0;
Zdenek Prikryl 14baa0
+			if (creds.uid != 0 && non_root_clients >= clientmax) {
Zdenek Prikryl 14baa0
+				close(cli_fd);
Zdenek Prikryl 14baa0
+				acpid_log(LOG_ERR,
Zdenek Prikryl 14baa0
+				    "too many non-root clients\n");
Zdenek Prikryl 14baa0
 				continue;
Zdenek Prikryl 14baa0
 			}
Zdenek Prikryl 14baa0
+			if (creds.uid != 0) {
Zdenek Prikryl 14baa0
+				non_root_clients++;
Zdenek Prikryl 14baa0
+			}
Zdenek Prikryl 14baa0
 			fcntl(cli_fd, F_SETFD, FD_CLOEXEC);
Zdenek Prikryl 14baa0
 			snprintf(buf, sizeof(buf)-1, "%d[%d:%d]",
Zdenek Prikryl 14baa0
 				creds.pid, creds.uid, creds.gid);
Zdenek Prikryl 14baa0
@@ -289,7 +313,7 @@
Zdenek Prikryl 14baa0
 		}
Zdenek Prikryl 14baa0
 	}
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
-	clean_exit(EXIT_SUCCESS);
Zdenek Prikryl 14baa0
+	clean_exit_with_status(EXIT_SUCCESS);
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 	return 0;
Zdenek Prikryl 14baa0
 }
Zdenek Prikryl 14baa0
@@ -302,6 +326,7 @@
Zdenek Prikryl 14baa0
 {
Zdenek Prikryl 14baa0
 	struct option opts[] = {
Zdenek Prikryl 14baa0
 		{"confdir", 1, 0, 'c'},
Zdenek Prikryl 14baa0
+		{"clientmax", 1, 0, 'C'},
Zdenek Prikryl 14baa0
 		{"debug", 0, 0, 'd'},
Zdenek Prikryl 14baa0
 		{"eventfile", 1, 0, 'e'},
Zdenek Prikryl 14baa0
 		{"foreground", 0, 0, 'f'},
Zdenek Prikryl 14baa0
@@ -318,6 +343,7 @@
Zdenek Prikryl 14baa0
 	};
Zdenek Prikryl 14baa0
 	const char *opts_help[] = {
Zdenek Prikryl 14baa0
 		"Set the configuration directory.",	/* confdir */
Zdenek Prikryl 14baa0
+		"Set the limit on non-root socket connections.",/* clientmax */
Zdenek Prikryl 14baa0
 		"Increase debugging level (implies -f).",/* debug */
Zdenek Prikryl 14baa0
 		"Use the specified file for events.",	/* eventfile */
Zdenek Prikryl 14baa0
 		"Run in the foreground.",		/* foreground */
Zdenek Prikryl 14baa0
@@ -338,7 +364,7 @@
Zdenek Prikryl 14baa0
 	for (;;) {
Zdenek Prikryl 14baa0
 		int i;
Zdenek Prikryl 14baa0
 		i = getopt_long(*argc, *argv,
Zdenek Prikryl 14baa0
-		    "c:de:flg:m:s:Sp:L:vh", opts, NULL);
Zdenek Prikryl 14baa0
+		    "c:C:de:flg:m:s:Sp:L:vh", opts, NULL);
Zdenek Prikryl 14baa0
 		if (i == -1) {
Zdenek Prikryl 14baa0
 			break;
Zdenek Prikryl 14baa0
 		}
Zdenek Prikryl 14baa0
@@ -346,6 +372,9 @@
Zdenek Prikryl 14baa0
 		case 'c':
Zdenek Prikryl 14baa0
 			confdir = optarg;
Zdenek Prikryl 14baa0
 			break;
Zdenek Prikryl 14baa0
+		case 'C':
Zdenek Prikryl 14baa0
+			clientmax = strtol(optarg, NULL, 0);
Zdenek Prikryl 14baa0
+			break;
Zdenek Prikryl 14baa0
 		case 'd':
Zdenek Prikryl 14baa0
 			foreground = 1;
Zdenek Prikryl 14baa0
 			acpid_debug++;
Zdenek Prikryl 14baa0
@@ -519,12 +548,18 @@
Zdenek Prikryl 14baa0
 }
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 static void
Zdenek Prikryl 14baa0
-clean_exit(int sig __attribute__((unused)))
Zdenek Prikryl 14baa0
+clean_exit_with_status(int status)
Zdenek Prikryl 14baa0
 {
Zdenek Prikryl 14baa0
 	acpid_cleanup_rules(1);
Zdenek Prikryl 14baa0
 	acpid_log(LOG_NOTICE, "exiting\n");
Zdenek Prikryl 14baa0
 	unlink(pidfile);
Zdenek Prikryl 14baa0
-	exit(EXIT_SUCCESS);
Zdenek Prikryl 14baa0
+	exit(status);
Zdenek Prikryl 14baa0
+}
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+static void
Zdenek Prikryl 14baa0
+clean_exit(int sig __attribute__((unused)))
Zdenek Prikryl 14baa0
+{
Zdenek Prikryl 14baa0
+	clean_exit_with_status(EXIT_SUCCESS);
Zdenek Prikryl 14baa0
 }
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 static void
Zdenek Prikryl 14baa0
--- acpid.h	2008/10/27 06:08:20	1.14
Zdenek Prikryl 14baa0
+++ acpid.h	2009/04/22 18:22:28	1.15
Zdenek Prikryl 14baa0
@@ -34,6 +34,7 @@
Zdenek Prikryl 14baa0
 #define ACPID_CONFDIR		"/etc/acpi/events"
Zdenek Prikryl 14baa0
 #define ACPID_SOCKETFILE	"/var/run/acpid.socket"
Zdenek Prikryl 14baa0
 #define ACPID_SOCKETMODE	0666
Zdenek Prikryl 14baa0
+#define ACPID_CLIENTMAX		256
Zdenek Prikryl 14baa0
 #define ACPID_PIDFILE		"/var/run/acpid.pid"
Zdenek Prikryl 14baa0
 #define ACPID_LOCKFILE		"/var/lock/acpid"
Zdenek Prikryl 14baa0
 #define ACPID_MAX_ERRS		5
Zdenek Prikryl 14baa0
@@ -45,6 +46,7 @@
Zdenek Prikryl 14baa0
  */
Zdenek Prikryl 14baa0
 extern int acpid_debug;
Zdenek Prikryl 14baa0
 extern int logevents;
Zdenek Prikryl 14baa0
+extern int non_root_clients;
Zdenek Prikryl 14baa0
 extern int acpid_log(int level, const char *fmt, ...);
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 /*
Zdenek Prikryl 14baa0
@@ -54,5 +56,6 @@
Zdenek Prikryl 14baa0
 extern int acpid_add_client(int client, const char *origin);
Zdenek Prikryl 14baa0
 extern int acpid_cleanup_rules(int do_detach);
Zdenek Prikryl 14baa0
 extern int acpid_handle_event(const char *event);
Zdenek Prikryl 14baa0
+extern void acpid_close_dead_clients(void);
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 #endif /* ACPID_H__ */
Zdenek Prikryl 14baa0
--- event.c	2008/10/27 05:28:12	1.21
Zdenek Prikryl 14baa0
+++ event.c	2009/04/22 18:22:28	1.22
Zdenek Prikryl 14baa0
@@ -23,6 +23,7 @@
Zdenek Prikryl 14baa0
 #include <sys/types.h>
Zdenek Prikryl 14baa0
 #include <sys/stat.h>
Zdenek Prikryl 14baa0
 #include <sys/wait.h>
Zdenek Prikryl 14baa0
+#include <sys/poll.h>
Zdenek Prikryl 14baa0
 #include <fcntl.h>
Zdenek Prikryl 14baa0
 #include <unistd.h>
Zdenek Prikryl 14baa0
 #include <stdio.h>
Zdenek Prikryl 14baa0
@@ -35,6 +36,7 @@
Zdenek Prikryl 14baa0
 #include <signal.h>
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 #include "acpid.h"
Zdenek Prikryl 14baa0
+#include "ud_socket.h"
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 /*
Zdenek Prikryl 14baa0
  * What is a rule?  It's polymorphic, pretty much.
Zdenek Prikryl 14baa0
@@ -449,6 +451,55 @@
Zdenek Prikryl 14baa0
 	free(r);
Zdenek Prikryl 14baa0
 }
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
+static int
Zdenek Prikryl 14baa0
+client_is_dead(int fd)
Zdenek Prikryl 14baa0
+{
Zdenek Prikryl 14baa0
+	struct pollfd pfd;
Zdenek Prikryl 14baa0
+	int r;
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+	/* check the fd to see if it is dead */
Zdenek Prikryl 14baa0
+	pfd.fd = fd;
Zdenek Prikryl 14baa0
+	pfd.events = POLLERR | POLLHUP;
Zdenek Prikryl 14baa0
+	r = poll(&pfd, 1, 0);
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+	if (r < 0) {
Zdenek Prikryl 14baa0
+		acpid_log(LOG_ERR, "poll(): %s\n", strerror(errno));
Zdenek Prikryl 14baa0
+		return 0;
Zdenek Prikryl 14baa0
+	}
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+	return pfd.revents;
Zdenek Prikryl 14baa0
+}
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+void
Zdenek Prikryl 14baa0
+acpid_close_dead_clients(void)
Zdenek Prikryl 14baa0
+{
Zdenek Prikryl 14baa0
+	struct rule *p;
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+	lock_rules();
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+	/* scan our client list */
Zdenek Prikryl 14baa0
+	p = client_list.head;
Zdenek Prikryl 14baa0
+	while (p) {
Zdenek Prikryl 14baa0
+		struct rule *next = p->next;
Zdenek Prikryl 14baa0
+		if (client_is_dead(p->action.fd)) {
Zdenek Prikryl 14baa0
+			struct ucred cred;
Zdenek Prikryl 14baa0
+			/* closed */
Zdenek Prikryl 14baa0
+			acpid_log(LOG_NOTICE,
Zdenek Prikryl 14baa0
+			    "client %s has disconnected\n", p->origin);
Zdenek Prikryl 14baa0
+			delist_rule(&client_list, p);
Zdenek Prikryl 14baa0
+			ud_get_peercred(p->action.fd, &cred);
Zdenek Prikryl 14baa0
+			if (cred.uid != 0) {
Zdenek Prikryl 14baa0
+				non_root_clients--;
Zdenek Prikryl 14baa0
+			}
Zdenek Prikryl 14baa0
+			close(p->action.fd);
Zdenek Prikryl 14baa0
+			free_rule(p);
Zdenek Prikryl 14baa0
+		}
Zdenek Prikryl 14baa0
+		p = next;
Zdenek Prikryl 14baa0
+	}
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
+	unlock_rules();
Zdenek Prikryl 14baa0
+}
Zdenek Prikryl 14baa0
+
Zdenek Prikryl 14baa0
 /*
Zdenek Prikryl 14baa0
  * the main hook for propogating events
Zdenek Prikryl 14baa0
  */
Zdenek Prikryl 14baa0
@@ -616,10 +667,15 @@
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 	r = safe_write(client, event, strlen(event));
Zdenek Prikryl 14baa0
 	if (r < 0 && errno == EPIPE) {
Zdenek Prikryl 14baa0
+		struct ucred cred;
Zdenek Prikryl 14baa0
 		/* closed */
Zdenek Prikryl 14baa0
 		acpid_log(LOG_NOTICE,
Zdenek Prikryl 14baa0
 		    "client %s has disconnected\n", rule->origin);
Zdenek Prikryl 14baa0
 		delist_rule(&client_list, rule);
Zdenek Prikryl 14baa0
+		ud_get_peercred(rule->action.fd, &cred);
Zdenek Prikryl 14baa0
+		if (cred.uid != 0) {
Zdenek Prikryl 14baa0
+			non_root_clients--;
Zdenek Prikryl 14baa0
+		}
Zdenek Prikryl 14baa0
 		close(rule->action.fd);
Zdenek Prikryl 14baa0
 		free_rule(rule);
Zdenek Prikryl 14baa0
 		return -1;
Zdenek Prikryl 14baa0
--- ud_socket.c	2005/08/19 06:56:21	1.5
Zdenek Prikryl 14baa0
+++ ud_socket.c	2009/04/22 18:22:28	1.6
Zdenek Prikryl 14baa0
@@ -1,5 +1,5 @@
Zdenek Prikryl 14baa0
 /*
Zdenek Prikryl 14baa0
- * $Id: acpid-1.0.8-socket.patch,v 1.1 2009/04/23 13:58:56 zprikryl Exp $
Zdenek Prikryl 14baa0
+ * $Id: acpid-1.0.8-socket.patch,v 1.1 2009/04/23 13:58:56 zprikryl Exp $
Zdenek Prikryl 14baa0
  * A few  routines for handling UNIX domain sockets
Zdenek Prikryl 14baa0
  */
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
@@ -103,3 +103,10 @@
Zdenek Prikryl 14baa0
 	return fd;
Zdenek Prikryl 14baa0
 }
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
+int
Zdenek Prikryl 14baa0
+ud_get_peercred(int fd, struct ucred *cred)
Zdenek Prikryl 14baa0
+{
Zdenek Prikryl 14baa0
+	socklen_t len = sizeof(struct ucred);
Zdenek Prikryl 14baa0
+	getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &len;;
Zdenek Prikryl 14baa0
+	return 0;
Zdenek Prikryl 14baa0
+}
Zdenek Prikryl 14baa0
--- ud_socket.h	2003/11/17 21:24:58	1.2
Zdenek Prikryl 14baa0
+++ ud_socket.h	2009/04/22 18:22:28	1.3
Zdenek Prikryl 14baa0
@@ -1,5 +1,5 @@
Zdenek Prikryl 14baa0
 /*
Zdenek Prikryl 14baa0
- *$Id: acpid-1.0.8-socket.patch,v 1.1 2009/04/23 13:58:56 zprikryl Exp $
Zdenek Prikryl 14baa0
+ *$Id: acpid-1.0.8-socket.patch,v 1.1 2009/04/23 13:58:56 zprikryl Exp $
Zdenek Prikryl 14baa0
  */
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 #ifndef UD_SOCKET_H__
Zdenek Prikryl 14baa0
@@ -11,5 +11,6 @@
Zdenek Prikryl 14baa0
 int ud_create_socket(const char *name);
Zdenek Prikryl 14baa0
 int ud_accept(int sock, struct ucred *cred);
Zdenek Prikryl 14baa0
 int ud_connect(const char *name);
Zdenek Prikryl 14baa0
+int ud_get_peercred(int fd, struct ucred *cred);
Zdenek Prikryl 14baa0
 
Zdenek Prikryl 14baa0
 #endif