1
From 1b911148009f696717da0b676d6d10af85d5aefb Mon Sep 17 00:00:00 2001
2
From: Emilio Pozuelo Monfort <pochu27@gmail.com>
3
Date: Sat, 17 Jul 2010 22:09:13 +0200
4
Subject: [PATCH] Add support to send file descriptors over Unix sockets
7
sysdeps/mach/hurd/recvmsg.c | 108 ++++++++++++++++++++++++++++++++++++++++++--
8
sysdeps/mach/hurd/sendmsg.c | 73 ++++++++++++++++++++++++-----
9
2 files changed, 166 insertions(+), 15 deletions(-)
11
--- a/sysdeps/mach/hurd/recvmsg.c
12
+++ b/sysdeps/mach/hurd/recvmsg.c
14
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
15
+/* Copyright (C) 2001, 2002, 2010 Free Software Foundation, Inc.
16
This file is part of the GNU C Library.
18
The GNU C Library is free software; you can redistribute it and/or
22
mach_msg_type_number_t len = 0;
24
+ mach_port_t *ports, *newports;
25
mach_msg_type_number_t nports = 0;
26
+ struct cmsghdr *cmsg;
28
mach_msg_type_number_t clen = 0;
35
+ error_t reauthenticate (mach_port_t port, mach_port_t *result)
39
+ ref = __mach_reply_port ();
41
+ err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
42
+ while (err == EINTR);
45
+ err = __USEPORT (AUTH, __auth_user_authenticate (port,
46
+ ref, MACH_MSG_TYPE_MAKE_SEND,
48
+ while (err == EINTR);
49
+ __mach_port_destroy (__mach_task_self (), ref);
53
/* Find the total number of bytes to be read. */
56
message->msg_controllen = clen;
57
memcpy (message->msg_control, cdata, message->msg_controllen);
59
+ /* SCM_RIGHTS ports. */
62
+ newports = __alloca (nports * sizeof (mach_port_t));
64
+ /* Reauthenticate all ports here. */
65
+ for (i = 0; i < nports; i++)
67
+ err = reauthenticate (ports[i], &newports[i]);
68
+ __mach_port_deallocate (__mach_task_self (), ports[i]);
71
+ for (j = 0; j < i; j++)
72
+ __mach_port_deallocate (__mach_task_self (), newports[j]);
73
+ for (j = i+1; j < nports; j++)
74
+ __mach_port_deallocate (__mach_task_self (), ports[j]);
76
+ __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
82
+ for (cmsg = CMSG_FIRSTHDR (message);
84
+ cmsg = CMSG_NXTHDR (message, cmsg))
86
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
88
+ fds = (int *) CMSG_DATA (cmsg);
89
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
92
+ for (i = 0; i < nfds && j < nports; i++)
94
+ /* The fd's flags are passed in the control data. */
95
+ fds[i] = _hurd_intern_fd (newports[j++], fds[i], 0);
111
+ /* Clean up all the file descriptors. */
114
+ for (cmsg = CMSG_FIRSTHDR (message);
116
+ cmsg = CMSG_NXTHDR (message, cmsg))
118
+ if (cmsg->cmsg_level == SOL_SOCKET
119
+ && cmsg->cmsg_type == SCM_RIGHTS)
121
+ fds = (int *) CMSG_DATA (cmsg);
122
+ nfds = (cmsg->cmsg_len
123
+ - CMSG_ALIGN (sizeof (struct cmsghdr)))
125
+ for (i = 0; i < nfds && j < nports; i++, j++)
126
+ _hurd_fd_close (_hurd_fd_get (fds[i]));
130
+ for (; j < nports; j++)
131
+ __mach_port_deallocate (__mach_task_self (), newports[j]);
133
+ __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
138
__vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
141
--- a/sysdeps/mach/hurd/sendmsg.c
142
+++ b/sysdeps/mach/hurd/sendmsg.c
144
-/* Copyright (C) 2001,2002,2004 Free Software Foundation, Inc.
145
+/* Copyright (C) 2001,2002,2004,2010 Free Software Foundation, Inc.
146
This file is part of the GNU C Library.
148
The GNU C Library is free software; you can redistribute it and/or
150
__libc_sendmsg (int fd, const struct msghdr *message, int flags)
153
+ struct cmsghdr *cmsg;
154
+ mach_port_t *ports = NULL;
155
+ mach_msg_type_number_t nports = 0;
157
struct sockaddr_un *addr = message->msg_name;
158
socklen_t addr_len = message->msg_namelen;
159
addr_port_t aport = MACH_PORT_NULL;
161
mach_msg_type_number_t len;
162
mach_msg_type_number_t amount;
167
/* Find the total number of bytes to be written. */
172
+ /* SCM_RIGHTS support: get the number of fds to send. */
173
+ cmsg = CMSG_FIRSTHDR (message);
174
+ for (; cmsg; cmsg = CMSG_NXTHDR (message, cmsg))
175
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
176
+ nports += (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
180
+ ports = __alloca (nports * sizeof (mach_port_t));
183
+ for (cmsg = CMSG_FIRSTHDR (message);
185
+ cmsg = CMSG_NXTHDR (message, cmsg))
187
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
189
+ fds = (int *) CMSG_DATA (cmsg);
190
+ nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
193
+ for (i = 0; i < nfds; i++)
195
+ err = HURD_DPORT_USE
198
+ err = __io_restrict_auth (port, &ports[nports],
202
+ /* We pass the flags in the control data. */
203
+ fds[i] = descriptor->flags;
214
if (addr->sun_family == AF_LOCAL)
216
file_t file = __file_name_lookup (addr->sun_path, 0, 0);
217
if (file == MACH_PORT_NULL)
220
- __vm_deallocate (__mach_task_self (), data.addr, len);
225
err = __ifsock_getsockaddr (file, &aport);
226
__mach_port_deallocate (__mach_task_self (), file);
228
/* The file did not grok the ifsock protocol. */
233
- __vm_deallocate (__mach_task_self (), data.addr, len);
234
- return __hurd_fail (err);
242
err = __socket_send (port, aport,
243
flags, data.ptr, len,
245
- MACH_MSG_TYPE_COPY_SEND, 0,
247
+ MACH_MSG_TYPE_COPY_SEND,
249
message->msg_control,
250
message->msg_controllen,
252
@@ -153,11 +194,19 @@
259
+ for (i = 0; i < nports; i++)
260
+ __mach_port_deallocate (__mach_task_self (), ports[i]);
263
__vm_deallocate (__mach_task_self (), data.addr, len);
265
- return err ? __hurd_sockfail (fd, flags, err) : amount;
267
+ return err ? __hurd_sockfail (fd, flags, err) : amount;
269
+ return __hurd_fail (err);
272
weak_alias (__libc_sendmsg, sendmsg)