[gnome-keyring] Fix endless loop in reading data.



commit 6c25bf1ba2772ac56e9f0430661290a40cbefed1
Author: Stef Walter <stef memberwebs com>
Date:   Mon Mar 8 04:39:18 2010 +0000

    Fix endless loop in reading data.
    
    Fix problems with EINTR and EAGAIN handling, and some possible
    endless loops in various places.
    
    Fixes bug #610678

 daemon/control/gkd-control-server.c |   16 +++++++++++-----
 daemon/prompt/gkd-prompt-tool.c     |    4 +++-
 daemon/ssh-agent/gkd-ssh-agent.c    |   19 +++++++++++--------
 pkcs11/gck/gck-data-file.c          |   26 +++++++++++++++-----------
 4 files changed, 40 insertions(+), 25 deletions(-)
---
diff --git a/daemon/control/gkd-control-server.c b/daemon/control/gkd-control-server.c
index db7ea29..18d4bf7 100644
--- a/daemon/control/gkd-control-server.c
+++ b/daemon/control/gkd-control-server.c
@@ -169,9 +169,11 @@ control_output (GIOChannel *channel, GIOCondition cond, gpointer user_data)
 
 	if (cond & G_IO_OUT) {
 		res = write (fd, buffer->buf + cdata->position, buffer->len - cdata->position);
-		if (res <= 0) {
+		if (res < 0) {
 			if (errno != EAGAIN && errno != EINTR)
 				cdata->position = buffer->len;
+		} else if (res == 0) {
+			cdata->position = buffer->len;
 		} else {
 			cdata->position += res;
 			g_assert (cdata->position <= buffer->len);
@@ -247,7 +249,7 @@ control_input (GIOChannel *channel, GIOCondition cond, gpointer user_data)
 		/* Time for reading credentials */
 		if (cdata->position == 0) {
 			if (egg_unix_credentials_read (fd, &pid, &uid) < 0) {
-				if (errno != EAGAIN || errno != EINTR)
+				if (errno != EAGAIN && errno != EINTR)
 					finished = TRUE;
 			} else if (getuid () != uid) {
 				g_message ("control request from bad uid: %u, should be %u\n", uid, getuid ());
@@ -260,9 +262,11 @@ control_input (GIOChannel *channel, GIOCondition cond, gpointer user_data)
 		} else if (egg_buffer_length (buffer) < 4) {
 			egg_buffer_reserve (buffer, 4);
 			res = read (fd, buffer->buf + buffer->len, 4 - buffer->len);
-			if (res <= 0) {
-				if (errno != EAGAIN || errno != EINTR)
+			if (res < 0) {
+				if (errno != EAGAIN && errno != EINTR)
 					finished = TRUE;
+			} else if (res == 0) {
+				finished = TRUE;
 			} else {
 				buffer->len += res;
 			}
@@ -276,9 +280,11 @@ control_input (GIOChannel *channel, GIOCondition cond, gpointer user_data)
 				g_assert (buffer->len < packet_size);
 				egg_buffer_reserve (buffer, packet_size);
 				res = read (fd, buffer->buf + buffer->len, packet_size - buffer->len);
-				if (res <= 0) {
+				if (res < 0) {
 					if (errno != EAGAIN && errno != EINTR)
 						finished = TRUE;
+				} else if (res == 0) {
+					finished = TRUE;
 				} else {
 					buffer->len += res;
 					g_assert (buffer->len <= packet_size);
diff --git a/daemon/prompt/gkd-prompt-tool.c b/daemon/prompt/gkd-prompt-tool.c
index b98de97..19257f2 100644
--- a/daemon/prompt/gkd-prompt-tool.c
+++ b/daemon/prompt/gkd-prompt-tool.c
@@ -798,13 +798,15 @@ write_all_output (const gchar *data, gsize len)
 
 	while (len > 0) {
 		res = write (1, data, len);
-		if (res <= 0) {
+		if (res < 0) {
 			if (errno == EAGAIN || errno == EINTR)
 				continue;
 			if (errno != EPIPE)
 				g_warning ("couldn't write dialog response to output: %s",
 				           g_strerror (errno));
 			exit (1);
+		} else if (res == 0) {
+			g_warning ("couldn't write all dialog response to output");
 		} else  {
 			len -= res;
 			data += res;
diff --git a/daemon/ssh-agent/gkd-ssh-agent.c b/daemon/ssh-agent/gkd-ssh-agent.c
index 0a851ce..50a1b79 100644
--- a/daemon/ssh-agent/gkd-ssh-agent.c
+++ b/daemon/ssh-agent/gkd-ssh-agent.c
@@ -56,12 +56,13 @@ read_all (int fd, guchar *buf, int len)
 
 		res = read (fd, buf, len);
 
-		if (res <= 0) {
-			if (errno == EAGAIN && errno == EINTR)
+		if (res < 0) {
+			if (errno == EAGAIN || errno == EINTR)
 				continue;
-			if (res < 0)
-				g_warning ("couldn't read %u bytes from client: %s", all,
-				           g_strerror (errno));
+			g_warning ("couldn't read %u bytes from client: %s", all,
+			           g_strerror (errno));
+			return FALSE;
+		} else if (res == 0) {
 			return FALSE;
 		} else  {
 			len -= res;
@@ -81,13 +82,15 @@ write_all (int fd, const guchar *buf, int len)
 	while (len > 0) {
 
 		res = write (fd, buf, len);
-
-		if (res <= 0) {
+		if (res < 0) {
 			if (errno == EAGAIN && errno == EINTR)
 				continue;
 			if (errno != EPIPE)
 				g_warning ("couldn't write %u bytes to client: %s", all,
-				           res < 0 ? g_strerror (errno) : "");
+				           g_strerror (errno));
+			return FALSE;
+		} else if (res == 0) {
+			g_warning ("couldn't write %u bytes to client", all);
 			return FALSE;
 		} else  {
 			len -= res;
diff --git a/pkcs11/gck/gck-data-file.c b/pkcs11/gck/gck-data-file.c
index e4e8c27..54d794f 100644
--- a/pkcs11/gck/gck-data-file.c
+++ b/pkcs11/gck/gck-data-file.c
@@ -132,23 +132,25 @@ read_all_bytes (int fd, guchar *buf, gsize len)
 {
 	gsize all = len;
 	int res;
-	
+
 	while (len > 0) {
-		
 		res = read (fd, buf, len);
-		if (res <= 0) {
+		if (res < 0) {
 			if (errno == EAGAIN || errno == EINTR)
 				continue;
-			if (res < 0 || len != all)
-				g_warning ("couldn't read %u bytes from store file: %s", 
-				           (guint)all, g_strerror (errno));
+			g_warning ("couldn't read %u bytes from store file: %s",
+			           (guint)all, g_strerror (errno));
+			return FALSE;
+		} else if (res == 0) {
+			if (len != all)
+				g_warning ("couldn't read %u bytes from store file", (guint)all);
 			return FALSE;
 		} else  {
 			len -= res;
 			buf += res;
 		}
 	}
-	
+
 	return TRUE;
 }
 
@@ -161,12 +163,14 @@ write_all_bytes (int fd, const guchar *buf, gsize len)
 	while (len > 0) {
 		
 		res = write (fd, buf, len);
-
-		if (res <= 0) {
+		if (res < 0) {
 			if (errno == EAGAIN || errno == EINTR)
 				continue;
 			g_warning ("couldn't write %u bytes to store file: %s", 
-			           (guint)all, res < 0 ? g_strerror (errno) : "");
+			           (guint)all, g_strerror (errno));
+			return FALSE;
+		} else if (res == 0) {
+			g_warning ("couldn't write %u bytes to store file", (guint)all);
 			return FALSE;
 		} else  {
 			len -= res;
@@ -219,7 +223,7 @@ parse_file_blocks (int file, BlockFunc block_func, GckSecret *login, gpointer us
 		if (!egg_buffer_get_uint32 (&buffer, offset, &offset, &length) ||
 		    !egg_buffer_get_uint32 (&buffer, offset, &offset, &block) || 
 		    length < 8) {
-			res = GCK_DATA_SUCCESS;
+			res = GCK_DATA_FAILURE;
 			g_message ("invalid block size or length in store file");
 			break;
 		}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]