mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
hurd: Support sending file descriptors over Unix sockets
This commit is contained in:
parent
9ae967bf45
commit
344e755248
2 changed files with 157 additions and 13 deletions
|
@ -32,13 +32,34 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
|
||||||
addr_port_t aport;
|
addr_port_t aport;
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
mach_msg_type_number_t len = 0;
|
mach_msg_type_number_t len = 0;
|
||||||
mach_port_t *ports;
|
mach_port_t *ports, *newports = NULL;
|
||||||
mach_msg_type_number_t nports = 0;
|
mach_msg_type_number_t nports = 0;
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
char *cdata = NULL;
|
char *cdata = NULL;
|
||||||
mach_msg_type_number_t clen = 0;
|
mach_msg_type_number_t clen = 0;
|
||||||
size_t amount;
|
size_t amount;
|
||||||
char *buf;
|
char *buf;
|
||||||
int i;
|
int nfds, *opened_fds = NULL;
|
||||||
|
int i, ii, j;
|
||||||
|
int newfds;
|
||||||
|
|
||||||
|
error_t reauthenticate (mach_port_t port, mach_port_t *result)
|
||||||
|
{
|
||||||
|
error_t err;
|
||||||
|
mach_port_t ref;
|
||||||
|
ref = __mach_reply_port ();
|
||||||
|
do
|
||||||
|
err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
|
||||||
|
while (err == EINTR);
|
||||||
|
if (!err)
|
||||||
|
do
|
||||||
|
err = __USEPORT (AUTH, __auth_user_authenticate (port,
|
||||||
|
ref, MACH_MSG_TYPE_MAKE_SEND,
|
||||||
|
result));
|
||||||
|
while (err == EINTR);
|
||||||
|
__mach_port_destroy (__mach_task_self (), ref);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find the total number of bytes to be read. */
|
/* Find the total number of bytes to be read. */
|
||||||
amount = 0;
|
amount = 0;
|
||||||
|
@ -137,9 +158,81 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
|
||||||
message->msg_controllen = clen;
|
message->msg_controllen = clen;
|
||||||
memcpy (message->msg_control, cdata, message->msg_controllen);
|
memcpy (message->msg_control, cdata, message->msg_controllen);
|
||||||
|
|
||||||
|
if (nports > 0)
|
||||||
|
{
|
||||||
|
newports = __alloca (nports * sizeof (mach_port_t));
|
||||||
|
opened_fds = __alloca (nports * sizeof (int));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This counts how many ports we processed completely. */
|
||||||
|
i = 0;
|
||||||
|
/* This counts how many new fds we create. */
|
||||||
|
newfds = 0;
|
||||||
|
|
||||||
|
for (cmsg = CMSG_FIRSTHDR (message);
|
||||||
|
cmsg;
|
||||||
|
cmsg = CMSG_NXTHDR (message, cmsg))
|
||||||
|
{
|
||||||
|
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
|
||||||
|
{
|
||||||
|
/* SCM_RIGHTS support. */
|
||||||
|
/* The fd's flags are passed in the control data. */
|
||||||
|
int *fds = (int *) CMSG_DATA (cmsg);
|
||||||
|
nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
|
||||||
|
/ sizeof (int);
|
||||||
|
|
||||||
|
for (j = 0; j < nfds; j++)
|
||||||
|
{
|
||||||
|
err = reauthenticate (ports[i], &newports[newfds]);
|
||||||
|
if (err)
|
||||||
|
goto cleanup;
|
||||||
|
fds[j] = opened_fds[newfds] = _hurd_intern_fd (newports[newfds],
|
||||||
|
fds[j], 0);
|
||||||
|
if (fds[j] == -1)
|
||||||
|
{
|
||||||
|
err = errno;
|
||||||
|
__mach_port_deallocate (__mach_task_self (), newports[newfds]);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
newfds++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nports; i++)
|
||||||
|
__mach_port_deallocate (mach_task_self (), ports[i]);
|
||||||
|
|
||||||
__vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
|
__vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
|
||||||
|
|
||||||
return (buf - data);
|
return (buf - data);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
/* Clean up all the file descriptors from port 0 to i-1. */
|
||||||
|
if (nports > 0)
|
||||||
|
{
|
||||||
|
ii = 0;
|
||||||
|
newfds = 0;
|
||||||
|
for (cmsg = CMSG_FIRSTHDR (message);
|
||||||
|
cmsg;
|
||||||
|
cmsg = CMSG_NXTHDR (message, cmsg))
|
||||||
|
{
|
||||||
|
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
|
||||||
|
{
|
||||||
|
nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
|
||||||
|
/ sizeof (int);
|
||||||
|
for (j = 0; j < nfds && ii < i; j++, ii++, newfds++)
|
||||||
|
{
|
||||||
|
_hurd_fd_close (_hurd_fd_get (opened_fds[newfds]));
|
||||||
|
__mach_port_deallocate (__mach_task_self (), newports[newfds]);
|
||||||
|
__mach_port_deallocate (__mach_task_self (), ports[ii]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
|
||||||
|
return __hurd_fail (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
weak_alias (__libc_recvmsg, recvmsg)
|
weak_alias (__libc_recvmsg, recvmsg)
|
||||||
|
|
|
@ -32,6 +32,10 @@ ssize_t
|
||||||
__libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
__libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
||||||
{
|
{
|
||||||
error_t err = 0;
|
error_t err = 0;
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
mach_port_t *ports = NULL;
|
||||||
|
mach_msg_type_number_t nports = 0;
|
||||||
|
int *fds, nfds;
|
||||||
struct sockaddr_un *addr = message->msg_name;
|
struct sockaddr_un *addr = message->msg_name;
|
||||||
socklen_t addr_len = message->msg_namelen;
|
socklen_t addr_len = message->msg_namelen;
|
||||||
addr_port_t aport = MACH_PORT_NULL;
|
addr_port_t aport = MACH_PORT_NULL;
|
||||||
|
@ -44,6 +48,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
||||||
mach_msg_type_number_t len;
|
mach_msg_type_number_t len;
|
||||||
mach_msg_type_number_t amount;
|
mach_msg_type_number_t amount;
|
||||||
int dealloc = 0;
|
int dealloc = 0;
|
||||||
|
int socketrpc = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Find the total number of bytes to be written. */
|
/* Find the total number of bytes to be written. */
|
||||||
|
@ -101,6 +106,48 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Allocate enough room for ports. */
|
||||||
|
cmsg = CMSG_FIRSTHDR (message);
|
||||||
|
for (; cmsg; cmsg = CMSG_NXTHDR (message, cmsg))
|
||||||
|
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
|
||||||
|
nports += (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
|
||||||
|
/ sizeof (int);
|
||||||
|
|
||||||
|
if (nports)
|
||||||
|
ports = __alloca (nports * sizeof (mach_port_t));
|
||||||
|
|
||||||
|
nports = 0;
|
||||||
|
for (cmsg = CMSG_FIRSTHDR (message);
|
||||||
|
cmsg;
|
||||||
|
cmsg = CMSG_NXTHDR (message, cmsg))
|
||||||
|
{
|
||||||
|
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
|
||||||
|
{
|
||||||
|
/* SCM_RIGHTS support: send FDs. */
|
||||||
|
fds = (int *) CMSG_DATA (cmsg);
|
||||||
|
nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
|
||||||
|
/ sizeof (int);
|
||||||
|
|
||||||
|
for (i = 0; i < nfds; i++)
|
||||||
|
{
|
||||||
|
err = HURD_DPORT_USE
|
||||||
|
(fds[i],
|
||||||
|
({
|
||||||
|
err = __io_restrict_auth (port, &ports[nports],
|
||||||
|
0, 0, 0, 0);
|
||||||
|
if (! err)
|
||||||
|
nports++;
|
||||||
|
/* We pass the flags in the control data. */
|
||||||
|
fds[i] = descriptor->flags;
|
||||||
|
err;
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (addr)
|
if (addr)
|
||||||
{
|
{
|
||||||
if (addr->sun_family == AF_LOCAL)
|
if (addr->sun_family == AF_LOCAL)
|
||||||
|
@ -111,9 +158,8 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
||||||
file_t file = __file_name_lookup (name, 0, 0);
|
file_t file = __file_name_lookup (name, 0, 0);
|
||||||
if (file == MACH_PORT_NULL)
|
if (file == MACH_PORT_NULL)
|
||||||
{
|
{
|
||||||
if (dealloc)
|
err = errno;
|
||||||
__vm_deallocate (__mach_task_self (), data.addr, len);
|
goto out;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
err = __ifsock_getsockaddr (file, &aport);
|
err = __ifsock_getsockaddr (file, &aport);
|
||||||
__mach_port_deallocate (__mach_task_self (), file);
|
__mach_port_deallocate (__mach_task_self (), file);
|
||||||
|
@ -121,11 +167,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
||||||
/* The file did not grok the ifsock protocol. */
|
/* The file did not grok the ifsock protocol. */
|
||||||
err = ENOTSOCK;
|
err = ENOTSOCK;
|
||||||
if (err)
|
if (err)
|
||||||
{
|
goto out;
|
||||||
if (dealloc)
|
|
||||||
__vm_deallocate (__mach_task_self (), data.addr, len);
|
|
||||||
return __hurd_fail (err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = EIEIO;
|
err = EIEIO;
|
||||||
|
@ -144,8 +186,9 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
||||||
/* Send the data. */
|
/* Send the data. */
|
||||||
err = __socket_send (port, aport,
|
err = __socket_send (port, aport,
|
||||||
flags, data.ptr, len,
|
flags, data.ptr, len,
|
||||||
NULL,
|
ports,
|
||||||
MACH_MSG_TYPE_COPY_SEND, 0,
|
MACH_MSG_TYPE_COPY_SEND,
|
||||||
|
nports,
|
||||||
message->msg_control,
|
message->msg_control,
|
||||||
message->msg_controllen,
|
message->msg_controllen,
|
||||||
&amount);
|
&amount);
|
||||||
|
@ -154,11 +197,19 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
|
||||||
}
|
}
|
||||||
err;
|
err;
|
||||||
}));
|
}));
|
||||||
|
socketrpc = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
for (i = 0; i < nports; i++)
|
||||||
|
__mach_port_deallocate (__mach_task_self (), ports[i]);
|
||||||
|
|
||||||
if (dealloc)
|
if (dealloc)
|
||||||
__vm_deallocate (__mach_task_self (), data.addr, len);
|
__vm_deallocate (__mach_task_self (), data.addr, len);
|
||||||
|
|
||||||
return err ? __hurd_sockfail (fd, flags, err) : amount;
|
if (socketrpc)
|
||||||
|
return err ? __hurd_sockfail (fd, flags, err) : amount;
|
||||||
|
else
|
||||||
|
return __hurd_fail (err);
|
||||||
}
|
}
|
||||||
|
|
||||||
weak_alias (__libc_sendmsg, sendmsg)
|
weak_alias (__libc_sendmsg, sendmsg)
|
||||||
|
|
Loading…
Add table
Reference in a new issue