Changeset 3643
- Timestamp:
- 05/06/08 17:35:11
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
releases/modest/diablo/ChangeLog
r3638 r3643 1 2008-05-06 Jose Dapena Paz <jdapena@igalia.com> 2 3 * libtinymail-camel/camel-lite/camel/camel-tcp-stream-ssl.c: 4 Protect PR_Reads and writes to avoid calls to PR_Close before one of 5 them. Should avoid some crashes and bad memory accesses. 6 1 7 2008-04-30 Sergio Villar Senin <svillar@igalia.com> 2 8 releases/modest/diablo/libtinymail-camel/camel-lite/camel/camel-tcp-stream-ssl.c
r3592 r3643 87 87 static int stream_gettimeout (CamelTcpStream *stream); 88 88 89 static gboolean begin_read (CamelTcpStreamSSL *stream); 90 static void end_read (CamelTcpStreamSSL *stream); 91 static gint ssl_close (CamelTcpStreamSSL *stream); 92 89 93 90 94 struct _CamelTcpStreamSSLPrivate { … … 97 101 gboolean accepted; 98 102 CamelService *service; 103 guint reads; 104 GMutex *reads_lock; 105 gboolean scheduled_close; 99 106 }; 100 107 108 /* 109 * This method is used for making sure we don't close the ssl socket 110 * before all the scheduled reads are finished. It also rejects read 111 * if we have a pending close. 112 * 113 * The return value is FALSE when we didn't accept the request to begin 114 * a read operation. In this case we shouldn't call end_read. 115 */ 116 static inline gboolean 117 begin_read (CamelTcpStreamSSL *stream) 118 { 119 gboolean retval = TRUE; 120 121 g_mutex_lock (stream->priv->reads_lock); 122 if (stream->priv->scheduled_close) { 123 retval = FALSE; 124 } else { 125 stream->priv->reads ++; 126 camel_object_ref (stream); 127 } 128 g_mutex_unlock (stream->priv->reads_lock); 129 return retval; 130 } 131 132 /* 133 * This ends a read request started succesfully in begin_read. Then, if that 134 * method returns FALSE, we shouldn't call this. 135 * 136 * It checks if there's a close call delayed because of reads pending. It it's 137 * so, then it closes the socket and sets the sock reference to NULL. 138 */ 139 static inline void 140 end_read (CamelTcpStreamSSL *stream) 141 { 142 gboolean close; 143 g_mutex_lock (stream->priv->reads_lock); 144 stream->priv->reads --; 145 close = ((stream->priv->reads == 0) && (stream->priv->scheduled_close)); 146 g_mutex_unlock (stream->priv->reads_lock); 147 if (close) { 148 PR_Shutdown (stream->priv->sockfd, PR_SHUTDOWN_BOTH); 149 PR_Close (stream->priv->sockfd); 150 stream->priv->sockfd = NULL; 151 } 152 camel_object_unref (stream); 153 } 154 155 156 /* 157 * Closes the stream ssl socket, in case there are no reads pending, or sets 158 * this as requested. 159 */ 160 static gint 161 ssl_close (CamelTcpStreamSSL *stream) 162 { 163 gboolean close; 164 g_mutex_lock (stream->priv->reads_lock); 165 close = ((stream->priv->reads == 0) && (stream->priv->sockfd != NULL)); 166 if (stream->priv->sockfd != NULL) 167 stream->priv->scheduled_close = TRUE; 168 g_mutex_unlock (stream->priv->reads_lock); 169 if (close) { 170 PR_Shutdown (stream->priv->sockfd, PR_SHUTDOWN_BOTH); 171 if (PR_Close (stream->priv->sockfd) == PR_FAILURE) { 172 stream->priv->sockfd = NULL; 173 return -1; 174 } 175 stream->priv->sockfd = NULL; 176 } 177 return 0; 178 } 101 179 102 180 static void … … 145 223 146 224 stream->priv = g_new0 (struct _CamelTcpStreamSSLPrivate, 1); 225 stream->priv->reads_lock = g_mutex_new (); 147 226 } 148 227 … … 153 232 154 233 if (stream->priv->sockfd != NULL) { 155 PR_Shutdown (stream->priv->sockfd, PR_SHUTDOWN_BOTH); 156 PR_Close (stream->priv->sockfd); 234 ssl_close (stream); 157 235 } 158 236 159 237 if (stream->priv->session) 160 238 camel_object_unref(stream->priv->session); 239 240 g_mutex_free (stream->priv->reads_lock); 161 241 162 242 g_free (stream->priv->expected_host); … … 221 301 NSS_InitReadWrite (str); 222 302 has_init = TRUE; 303 g_free (str); 223 304 } 224 305 … … 362 443 } 363 444 445 g_mutex_lock (ssl->priv->reads_lock); 364 446 ssl->priv->sockfd = fd; 447 ssl->priv->scheduled_close = FALSE; 448 ssl->priv->reads = 0; 449 g_mutex_unlock (ssl->priv->reads_lock); 365 450 366 451 if (SSL_ResetHandshake (fd, FALSE) == SECFailure) { … … 425 510 do { 426 511 nread = -1; 427 if (PR_Available (tcp_stream_ssl->priv->sockfd) != 0) 428 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 512 if (begin_read (tcp_stream_ssl)) { 513 if (PR_Available (tcp_stream_ssl->priv->sockfd) != 0) 514 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 515 end_read (tcp_stream_ssl); 516 } 429 517 if (nread == -1) 430 518 set_errno (PR_GetError ()); … … 491 579 } else { 492 580 do { 493 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 494 if (nread == -1) 495 set_errno (PR_GetError ()); 581 nread = -1; 582 if (begin_read (tcp_stream_ssl)) { 583 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 584 if (nread == -1) 585 set_errno (PR_GetError ()); 586 end_read (tcp_stream_ssl); 587 } 496 588 } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 497 589 } … … 548 640 } else { 549 641 do { 550 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 551 if (nread == -1) 552 set_errno (PR_GetError ()); 642 nread = -1; 643 if (begin_read (tcp_stream_ssl)) { 644 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 645 if (nread == -1) 646 set_errno (PR_GetError ()); 647 end_read (tcp_stream_ssl); 648 } 553 649 } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 554 650 } … … 619 715 } else { 620 716 do { 621 w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); 622 if (w == -1) 623 set_errno (PR_GetError ()); 717 w = -1; 718 if (begin_read (tcp_stream_ssl)) { 719 w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); 720 if (w == -1) 721 set_errno (PR_GetError ()); 722 end_read (tcp_stream_ssl); 723 } 624 724 } while (w == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 625 725 … … 681 781 } else { 682 782 do { 683 w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); 684 if (w == -1) 685 set_errno (PR_GetError ()); 783 w = -1; 784 if (begin_read (tcp_stream_ssl)) { 785 w = PR_Write (tcp_stream_ssl->priv->sockfd, buffer + written, n - written); 786 if (w == -1) 787 set_errno (PR_GetError ()); 788 end_read (tcp_stream_ssl); 789 } 686 790 } while (w == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 687 791 … … 724 828 } 725 829 726 PR_Shutdown (((CamelTcpStreamSSL *)stream)->priv->sockfd, PR_SHUTDOWN_BOTH); 727 if (PR_Close (((CamelTcpStreamSSL *)stream)->priv->sockfd) == PR_FAILURE) 728 return -1; 830 ssl_close ((CamelTcpStreamSSL *) stream); 729 831 730 832 ((CamelTcpStreamSSL *)stream)->priv->sockfd = NULL; … … 1389 1491 PR_Shutdown (fd, PR_SHUTDOWN_BOTH); 1390 1492 PR_Close (fd); 1391 ssl->priv->sockfd = NULL;1392 1493 errno = errnosave; 1393 1494 … … 1398 1499 } 1399 1500 1501 g_mutex_lock (ssl->priv->reads_lock); 1502 ssl->priv->reads = 0; 1503 ssl->priv->scheduled_close = FALSE; 1400 1504 ssl->priv->sockfd = fd; 1505 g_mutex_unlock (ssl->priv->reads_lock); 1401 1506 1402 1507 return 0;
