bug-hurd
[Top][All Lists]
Advanced

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

socket_send & socket_recv fail when sending non-socket ports


From: Emilio Pozuelo Monfort
Subject: socket_send & socket_recv fail when sending non-socket ports
Date: Tue, 27 Jul 2010 17:39:08 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100619 Icedove/3.0.5

Hi,

While adding support for SCM_RIGHTS to glibc, I've created a testcase that sends
and receives some ports on the result of a socketpair() call. The ports sent
were initially the two ports result of another socketpair() call, and it was
working fine, but then I tried with the result of a couple of open() calls, and
socket_recv() was returning EMIGSERVERDIED.

I've reduced the testcase to not call glibc functions, so we see the problem is
in Hurd and not in my patch (which only touches glibc). The testcase has an #if
that you can toggle to 0 or 1. If at 0, it will send a socket's port and
everything will work, but if at 1, it will send a file's port and socket_recv
will send an error.

I have added some code to pflocal and socket_send seems to be working fine and
returning the correct number of ports (1 in this case). So I've stepped over the
MiG client stub for socket_send, and it has this:

        /* msgh_size passed as argument */
        InP->Head.msgh_request_port = sock;
        InP->Head.msgh_reply_port = __mig_get_reply_port();
        InP->Head.msgh_seqno = 0;
        InP->Head.msgh_id = 26015;

        msg_result = __mach_msg(&InP->Head,
MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, 40, sizeof(Reply),
InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
        if (msg_result != MACH_MSG_SUCCESS) {
                __mig_dealloc_reply_port(InP->Head.msgh_reply_port);
                return msg_result;
        }
        __mig_put_reply_port(InP->Head.msgh_reply_port);

        if (OutP->Head.msgh_id != 26115) {
                if (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
                return MIG_SERVER_DIED;
                else {
                        __mig_dealloc_reply_port(InP->Head.msgh_reply_port);
                        return MIG_REPLY_MISMATCH;
                }
        }



It's returning because of this:

        if (OutP->Head.msgh_id != 26115) {
                if (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
                return MIG_SERVER_DIED;

But I'm not sure how to interpret it, and why a non-socket port in the ports
argument would cause this.

Any ideas?

Regards,
Emilio



#define _GNU_SOURCE

#include <error.h>
#include <fcntl.h>
#include <sys/socket.h>

#include <hurd.h>
#include <hurd/fd.h>
#include <hurd/socket.h>

int
main (int argc, char **argv)
{
  error_t err;
  addr_port_t aport;
  socket_t server, sock1, sock2;
  int flags;
  mach_msg_type_number_t dlen, clen, amount;
  char *cdata, *data, c;
  mach_port_t *ports;
  mach_msg_type_number_t nports = 0;

  server = file_name_lookup ("/servers/socket/1", 0, 0);
  if (server == MACH_PORT_NULL)
    return -1;

  err = socket_create (server, SOCK_STREAM, 0, &sock1);
  if (! err)
    err = socket_create (server, SOCK_STREAM, 0, &sock2);
  if (! err)
    err = socket_connect2 (sock1, sock2);
  if (err)
    error (1, err, "could not create sockets");

#if 0
  file_t file = file_name_lookup ("/tmp/file1", 0, O_RDONLY);
  if (file == MACH_PORT_NULL)
    error (1, err, "file not found: %s", "/tmp/file1");
#else
  socket_t file;
  err = socket_create (server, SOCK_STREAM, 0, &file);
  if (err)
    error (1, err, "could not create socket");
#endif

  amount = 0;
  err = socket_send (sock1, MACH_PORT_NULL /* address */, 0 /* flags */,
                     &c, sizeof (c), &file, MACH_MSG_TYPE_MOVE_SEND, 1,
                     NULL /* control */, 0 /* len */, &amount);
  if (err)
    error (1, err, "socket_send");

  dlen = sizeof (data);
  err = socket_recv (sock2, &aport, 0 /* flags */,
                     &data, &dlen, &ports, &nports, &cdata, &clen,
                     &flags, amount);
  if (err)
    error (1, err, "socket_recv");

  return 0;
}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]