4
0
Эх сурвалжийг харах

Merge trunk revision 3029:
r3029 | asalkeld | 2010-08-24 18:13:14 -0700 (Tue, 24 Aug 2010) | 2 lines

IPC: return CS_ERR_NO_RESOURCES to library when low on fds.



git-svn-id: http://svn.fedorahosted.org/svn/corosync/branches/flatiron@3032 fd59a12c-fef9-0310-b244-a6a79926bd2f

Steven Dake 15 жил өмнө
parent
commit
9f37706468
4 өөрчлөгдсөн 61 нэмэгдсэн , 20 устгасан
  1. 31 19
      exec/coroipcs.c
  2. 3 1
      exec/main.c
  3. 21 0
      exec/util.h
  4. 6 0
      lib/util.h

+ 31 - 19
exec/coroipcs.c

@@ -85,6 +85,7 @@
 #else
 #include <sys/sem.h>
 #endif
+#include "util.h"
 
 #ifndef MSG_NOSIGNAL
 #define MSG_NOSIGNAL 0
@@ -760,14 +761,14 @@ retry_send:
 	return (0);
 }
 
-static int
+static cs_error_t
 req_setup_recv (
 	struct conn_info *conn_info)
 {
 	int res;
 	struct msghdr msg_recv;
 	struct iovec iov_recv;
-	int authenticated = 0;
+	cs_error_t auth_res = CS_ERR_LIBRARY;
 
 #ifdef COROSYNC_LINUX
 	struct cmsghdr *cmsg;
@@ -803,7 +804,7 @@ retry_recv:
 		goto retry_recv;
 	} else
 	if (res == -1 && errno != EAGAIN) {
-		return (0);
+		return (CS_ERR_LIBRARY);
 	} else
 	if (res == 0) {
 #if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
@@ -811,9 +812,9 @@ retry_recv:
 		 * EOF is detected when recvmsg return 0.
 		 */
 		ipc_disconnect (conn_info);
-		return 0;
+		return (CS_ERR_LIBRARY);
 #else
-		return (-1);
+		return (CS_ERR_SECURITY);
 #endif
 	}
 	conn_info->setup_bytes_read += res;
@@ -836,7 +837,9 @@ retry_recv:
 			egid = ucred_getegid (uc);
 			conn_info->client_pid = ucred_getpid (uc);
 			if (api->security_valid (euid, egid)) {
-				authenticated = 1;
+				auth_res = CS_OK;
+			} else {
+				auth_res = hdb_error_to_cs(errno);
 			}
 			ucred_free(uc);
 		}
@@ -858,7 +861,9 @@ retry_recv:
 		egid = -1;
 		if (getpeereid (conn_info->fd, &euid, &egid) == 0) {
 			if (api->security_valid (euid, egid)) {
-				authenticated = 1;
+				auth_res = CS_OK;
+			} else {
+				auth_res = hdb_error_to_cs(errno);
 			}
 		}
 	}
@@ -873,29 +878,36 @@ retry_recv:
 	if (cred) {
 		conn_info->client_pid = cred->pid;
 		if (api->security_valid (cred->uid, cred->gid)) {
-			authenticated = 1;
+			auth_res = CS_OK;
+		} else {
+			auth_res = hdb_error_to_cs(errno);
 		}
 	}
 
 #else /* no credentials */
-	authenticated = 1;
- 	log_printf (LOGSYS_LEVEL_ERROR, "Platform does not support IPC authentication.  Using no authentication\n");
+	auth_res = CS_OK;
+	log_printf (LOGSYS_LEVEL_ERROR, "Platform does not support IPC authentication.  Using no authentication\n");
 #endif /* no credentials */
 
-	if (authenticated == 0) {
-		log_printf (LOGSYS_LEVEL_ERROR, "Invalid IPC credentials.\n");
+	if (auth_res != CS_OK) {
 		ipc_disconnect (conn_info);
-		return (-1);
- 	}
+		if (auth_res == CS_ERR_NO_RESOURCES) {
+			log_printf (LOGSYS_LEVEL_ERROR,
+				"Not enough file desciptors for IPC connection.\n");
+		} else {
+			log_printf (LOGSYS_LEVEL_ERROR, "Invalid IPC credentials.\n");
+		}
+		return auth_res;
+	}
 
 	if (conn_info->setup_bytes_read == sizeof (mar_req_setup_t)) {
 #ifdef COROSYNC_LINUX
 		setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED,
 			&off, sizeof (off));
 #endif
-		return (1);
+		return (CS_OK);
 	}
-	return (0);
+	return (CS_ERR_LIBRARY);
 }
 
 static void ipc_disconnect (struct conn_info *conn_info)
@@ -1575,10 +1587,10 @@ int coroipcs_handler_dispatch (
 		 * send OK
 		 */
 		res = req_setup_recv (conn_info);
-		if (res == -1) {
-			req_setup_send (conn_info, CS_ERR_SECURITY);
+		if (res != CS_OK && res != CS_ERR_LIBRARY) {
+			req_setup_send (conn_info, res);
 		}
-		if (res != 1) {
+		if (res != CS_OK) {
 			return (0);
 		}
 

+ 3 - 1
exec/main.c

@@ -851,7 +851,8 @@ static int corosync_security_valid (int euid, int egid)
 	struct list_head *iter;
 
 	if (corosync_not_enough_fds_left) {
-		return 0;
+		errno = EMFILE;
+		return (0);
 	}
 
 	if (euid == 0 || egid == 0) {
@@ -868,6 +869,7 @@ static int corosync_security_valid (int euid, int egid)
 			return (1);
 	}
 
+	errno = EACCES;
 	return (0);
 }
 

+ 21 - 0
exec/util.h

@@ -65,6 +65,27 @@ enum e_ais_done {
 	AIS_DONE_ALREADY_RUNNING = 18,
 };
 
+static inline cs_error_t hdb_error_to_cs (int res)		\
+{								\
+	if (res == 0) {						\
+		return (CS_OK);					\
+	} else {						\
+		if (errno == EBADF) {				\
+			return (CS_ERR_BAD_HANDLE);		\
+		} else						\
+		if (errno == ENOMEM) {				\
+			return (CS_ERR_NO_MEMORY);		\
+		} else						\
+		if (errno == EMFILE) {				\
+			return (CS_ERR_NO_RESOURCES);		\
+		} else						\
+		if (errno == EACCES) {				\
+			return (CS_ERR_SECURITY);		\
+		}						\
+		return (CS_ERR_LIBRARY);			\
+	}							\
+}
+
 /*
  * Compare two names.  returns non-zero on match.
  */

+ 6 - 0
lib/util.h

@@ -48,6 +48,12 @@ static inline cs_error_t hdb_error_to_cs (int res)		\
 		} else						\
 		if (errno == ENOMEM) {				\
 			return (CS_ERR_NO_MEMORY);		\
+		} else						\
+		if (errno == EMFILE) {				\
+			return (CS_ERR_NO_RESOURCES);		\
+		} else						\
+		if (errno == EACCES) {				\
+			return (CS_ERR_SECURITY);		\
 		}						\
 		return (CS_ERR_LIBRARY);			\
 	}							\