ORBit-0.5.7 bug: non-root process can't talk to root process!



Hi, all,

It is very strange that ORBit-0.5.7 can't communicate with a root
process and non-root-user process.

For example, compiling with ORBit-0.5.7, the echo example works well if
the server and client are run by a same user, but if the server is run
by root and the client is run by the client, the client can't talk to
the server.

But with ORBit-0.5.2, I don't meet such kind of problem.  I think ORBit
shouldn't provide such kind of security and then there is a bug inside
ORBit-0.5.7.

Moreover, I believe there is another bug inside the function:
	giop_send_buffer_write ()
at file
	ORBit/src/IIOP/giop-msg-buffer.c, 
which causts the client hangs if the server is turned down while the
client is running.  I have reported this bug last week but no response,
so I post it again (I just want to make sure I have done the right
thing).

> From: Michael Rumpf <michael rumpfonline de>
> To: orbit-list gnome org
> Subject: Re: question object servers going
down
> Date: Wed, 13 Sep 2000 23:31:07 +0200
>
> Hi,
>
> I just tested this with the "echo-server"
> and the "echo-client IOR_of_Server 
> 10000" and took the server down while the
> client was running. The client 
> just hangs without any error message.

I had the same problem that the client just
hangs after the server is down.  

gdb says:

#0  0x40157dd3 in __writev (fd=7,
vector=0x804e988, count=11) at
../sysdeps/unix/sysv/linux/writev.c:50
#1  0x400202a0 in giop_send_buffer_write ()
from /usr/lib/libIIOP.so.0

...

And then I was refered to file
	ORBit-0.5.7/src/IIOP/giop-msg-buffer.c .
After carefully reading through the function
giop_send_buffer_write(), I think I found the bug inside that function.  

Function giop_send_buffer_write() calls writev() to send out the
buffer.  The first argument of writev() is a file descriptor fd. 
Certainly fd
could be invalid sometime.  For instance, in
the above echo example the server is down, then there is only one half
of TCP connection
termincation and nothing happens at the client.  If such event happens,
SIGPIPE will be throwed out.  Unfortunately, giop_send_buffer_write()
doesn't handle such event.

/* The modified code (by me) for function
 *	giop_send_buffer_write() 
 * at file 
 *	ORBit/src/IIOP/giop-msg-buffer.c
 */
gint
giop_send_buffer_write(GIOPSendBuffer *send_buffer)
{
  gulong nvecs;
  glong res=-1, sum, t;
  struct iovec *curvec;
  int fd;
  GIOPConnection *cnx;
  gint retval =
-1;                                                             

  cnx = GIOP_MESSAGE_BUFFER(send_buffer)->connection;
  if(!cnx->is_valid)
    return -1;
 
  fd = GIOP_CONNECTION_GET_FD(cnx);
  nvecs = GIOP_MESSAGE_BUFFER(send_buffer)->iovecs->len;
  curvec = (struct iovec
*)GIOP_MESSAGE_BUFFER(send_buffer)->iovecs->data;      

 /* If the peer process goes down while the local process is running,
  * there is just only one half of TCP connection termincation and
  * nothing happens at this side.  Then writev, actually write, will
  * throw a SIGPIPE event.  If SIGPIPE is ignored, errno is set as
  * EPIPE.  I use this way to fix this bug.
 
*/                                                                           
  signal(SIGPIPE, SIG_IGN);
  res = writev(fd, curvec, nvecs);
  signal(SIGPIPE, SIG_DFL);

 /* It makes more sense to check the writev return 
  * value right here instead of later.
*/                                                       
  if(res < 0) {
    if(errno == EPIPE) {
//      giop_main_handle_connection_exception(cnx);
        /* Sounds like giop_main_handle_connection_exception do too
much,
         * if it is directly called, CORBA_Enviorment ev's _major will
         * be set as CORBA_NO_EXCEPTION
        
*/                                                                     

      /* The following statements are just a copy 	of the original
       * giop_main_handle_connection_exception but I comment some out
       */
      giop_connection_ref(cnx);
 
//     
giop_connection_remove_from_list(cnx);                                  
        /* Sounds like if this connection cnx is removed from the global
         * giop_connection_list, CORBA_Enviorment ev's _major will be
         * set as CORBA_NO_EXCEPTION.  Then I have to comment it out.
         */
 
      shutdown(fd, 2);
//      close(fd);
//      GIOP_CONNECTION(cnx)->fd = -1;
//      cnx->is_valid =
FALSE;                                                  
        /* UNIX docments say after close a fd by close(), the fd
         * couldn't be used any more in that process.
         * Since this connection has not been removed from the global
         * list, this fd has been used later at somewhere.
         * Actually, using close(), I get some warning message.
         * On the other hand, shutdown() already closes this connection.
         */

      if(cnx->incoming_msg) {
        giop_recv_buffer_unuse(cnx->incoming_msg);
        cnx->incoming_msg = NULL;
     
}                                                                         

      giop_connection_unref(cnx);
      /* End of giop_main_handle_connection_exception. */
 
      goto out;
    }
    if(errno != EAGAIN) {
      giop_main_handle_connection_exception(cnx);
      goto out;
    }
 
    res = 0;
 
}                                                                             

  sum = (GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size +
sizeof(GIOPMessageHeader));

  if(res < sum) {
 
    /* wrote 7, iovecs 3, 2, 2, 4:
       0 + 3 !> 7
       3 + 2 !> 7
       5 + 2 !> 7
     */
 
    for(t = 0; ; t += curvec->iov_len, curvec++, nvecs--) {
      if((t + curvec->iov_len) > res)
        break;
    }  
    if((res - t) > 0) {
      curvec->iov_len -= (res - t);
      curvec->iov_base = (gpointer)((char *)curvec->iov_base + (res -
t));
    }  
 
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
 
    t = writev(fd, curvec,
nvecs);                                                                                                                                                                                

    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
 
    if((t < 0) || ((res + t) < sum)) {
        giop_main_handle_connection_exception(cnx);
        goto out;
    }
  }
 
  retval =
0;                                                                   
 out:
 
  return retval;
} 

/* The original source code for function
 *	giop_send_buffer_write() 
 * at file 
 *	ORBit/src/IIOP/giop-msg-buffer.c
 */
gint
giop_send_buffer_write(GIOPSendBuffer *send_buffer)
{
  gulong nvecs;
  glong res, sum, t;
  struct iovec *curvec;
  int fd;
  GIOPConnection *cnx;
  gint retval =
-1;                                                             

  cnx = GIOP_MESSAGE_BUFFER(send_buffer)->connection;
  if(!cnx->is_valid)
    return -1;
 
  fd = GIOP_CONNECTION_GET_FD(cnx);
  nvecs = GIOP_MESSAGE_BUFFER(send_buffer)->iovecs->len;
  curvec = (struct iovec
*)GIOP_MESSAGE_BUFFER(send_buffer)->iovecs->data;      

  res = writev(fd, curvec, nvecs);
 
  sum = (GIOP_MESSAGE_BUFFER(send_buffer)->message_header.message_size +
sizeof(GIOPMessageHeader));

  if(res < sum) {
    if(res < 0) {
      if(errno != EAGAIN) {
        giop_main_handle_connection_exception(cnx);
        goto out;
      }
 
      res =
0;                                                                  
    }
 
    /* wrote 7, iovecs 3, 2, 2, 4:
       0 + 3 !> 7
       3 + 2 !> 7
       5 + 2 !> 7
     */
 
    for(t = 0; ; t += curvec->iov_len, curvec++, nvecs--) {
      if((t + curvec->iov_len) > res)
        break;
    }  
    if((res - t) > 0) {
      curvec->iov_len -= (res - t);
      curvec->iov_base = (gpointer)((char *)curvec->iov_base + (res -
t));
    }  
 
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
 
    t = writev(fd, curvec,
nvecs);                                                                                                                                                                                

    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
 
    if((t < 0) || ((res + t) < sum)) {
        giop_main_handle_connection_exception(cnx);
        goto out;
    }
  }
 
  retval =
0;                                                                   
 out:
 
  return retval;
} 


Regards,
Yonghong




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