chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / debian / patches / hurd-i386 / local-sendmsg-SCM_RIGHTS.diff
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
5
6 diff --git a/sysdeps/mach/hurd/recvmsg.c b/sysdeps/mach/hurd/recvmsg.c
7 index 33897b8..0935c79 100644
8 --- a/sysdeps/mach/hurd/recvmsg.c
9 +++ b/sysdeps/mach/hurd/recvmsg.c
10 @@ -1,4 +1,4 @@
11 -/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
12 +/* Copyright (C) 2001, 2002, 2010 Free Software Foundation, Inc.
13     This file is part of the GNU C Library.
14  
15     The GNU C Library is free software; you can redistribute it and/or
16 @@ -33,13 +33,35 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
17    addr_port_t aport;
18    char *data = NULL;
19    mach_msg_type_number_t len = 0;
20 -  mach_port_t *ports;
21 +  mach_port_t *ports, *newports;
22    mach_msg_type_number_t nports = 0;
23 +  struct cmsghdr *cmsg;
24    char *cdata = NULL;
25    mach_msg_type_number_t clen = 0;
26    size_t amount;
27    char *buf;
28 -  int i;
29 +  int nfds, *fds;
30 +  int i, j;
31 +
32 +  auth_t auth;
33 +
34 +  error_t reauthenticate (mach_port_t port, mach_port_t *result)
35 +    {
36 +      error_t err;
37 +      mach_port_t ref;
38 +      ref = __mach_reply_port ();
39 +      do
40 +       err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
41 +      while (err == EINTR);
42 +      if (!err)
43 +       do
44 +         err = __auth_user_authenticate (auth,
45 +                                         ref, MACH_MSG_TYPE_MAKE_SEND,
46 +                                         result);
47 +       while (err == EINTR);
48 +      __mach_port_destroy (__mach_task_self (), ref);
49 +      return err;
50 +    }
51  
52    /* Find the total number of bytes to be read.  */
53    amount = 0;
54 @@ -136,6 +158,86 @@ __libc_recvmsg (int fd, struct msghdr *message, int flags)
55      message->msg_controllen = clen;
56    memcpy (message->msg_control, cdata, message->msg_controllen);
57  
58 +  /* SCM_RIGHTS ports.  */
59 +  if (nports > 0)
60 +    {
61 +      auth = getauth ();
62 +      newports = __alloca (nports * sizeof (mach_port_t));
63 +
64 +      /* Reauthenticate all ports here.  */
65 +      for (i = 0; i < nports; i++)
66 +       {
67 +         err = reauthenticate (ports[i], &newports[i]);
68 +         __mach_port_deallocate (__mach_task_self (), ports[i]);
69 +         if (err)
70 +           {
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]);
75 +
76 +             __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
77 +             __hurd_fail (err);
78 +           }
79 +       }
80 +
81 +      j = 0;
82 +      for (cmsg = CMSG_FIRSTHDR (message);
83 +          cmsg;
84 +          cmsg = CMSG_NXTHDR (message, cmsg))
85 +       {
86 +         if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
87 +           {
88 +             fds = (int *) CMSG_DATA (cmsg);
89 +             nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
90 +                    / sizeof (int);
91 +
92 +             for (i = 0; i < nfds && j < nports; i++)
93 +               {
94 +                 /* The fd's flags are passed in the control data.  */
95 +                 fds[i] = _hurd_intern_fd (newports[j++], fds[i], 0);
96 +                 if (fds[i] == -1)
97 +                   {
98 +                     err = errno;
99 +                     goto cleanup;
100 +                   }
101 +               }
102 +           }
103 +       }
104 +
105 +      if (j != nports)
106 +       err = EGRATUITOUS;
107 +
108 +      if (err)
109 +      cleanup:
110 +       {
111 +         /* Clean up all the file descriptors.  */
112 +         nports = j;
113 +         j = 0;
114 +         for (cmsg = CMSG_FIRSTHDR (message);
115 +              cmsg;
116 +              cmsg = CMSG_NXTHDR (message, cmsg))
117 +           {
118 +             if (cmsg->cmsg_level == SOL_SOCKET
119 +                 && cmsg->cmsg_type == SCM_RIGHTS)
120 +               {
121 +                 fds = (int *) CMSG_DATA (cmsg);
122 +                 nfds = (cmsg->cmsg_len
123 +                         - CMSG_ALIGN (sizeof (struct cmsghdr)))
124 +                        / sizeof (int);
125 +                 for (i = 0; i < nfds && j < nports; i++, j++)
126 +                   _hurd_fd_close (_hurd_fd_get (fds[i]));
127 +               }
128 +           }
129 +
130 +         for (; j < nports; j++)
131 +           __mach_port_deallocate (__mach_task_self (), newports[j]);
132 +
133 +         __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
134 +         __hurd_fail (err);
135 +       }
136 +    }
137 +
138    __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
139  
140    return (buf - data);
141 diff --git a/sysdeps/mach/hurd/sendmsg.c b/sysdeps/mach/hurd/sendmsg.c
142 index 118fd59..fb8dd2d 100644
143 --- a/sysdeps/mach/hurd/sendmsg.c
144 +++ b/sysdeps/mach/hurd/sendmsg.c
145 @@ -1,4 +1,4 @@
146 -/* Copyright (C) 2001,2002,2004 Free Software Foundation, Inc.
147 +/* Copyright (C) 2001,2002,2004,2010 Free Software Foundation, Inc.
148     This file is part of the GNU C Library.
149  
150     The GNU C Library is free software; you can redistribute it and/or
151 @@ -32,6 +32,10 @@ ssize_t
152  __libc_sendmsg (int fd, const struct msghdr *message, int flags)
153  {
154    error_t err = 0;
155 +  struct cmsghdr *cmsg;
156 +  mach_port_t *ports = NULL;
157 +  mach_msg_type_number_t nports = 0;
158 +  int *fds, nfds;
159    struct sockaddr_un *addr = message->msg_name;
160    socklen_t addr_len = message->msg_namelen;
161    addr_port_t aport = MACH_PORT_NULL;
162 @@ -44,6 +48,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
163    mach_msg_type_number_t len;
164    mach_msg_type_number_t amount;
165    int dealloc = 0;
166 +  int socketrpc = 0;
167    int i;
168  
169    /* Find the total number of bytes to be written.  */
170 @@ -101,6 +106,46 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
171         }
172      }
173  
174 +  /* SCM_RIGHTS support: get the number of fds to send.  */
175 +  cmsg = CMSG_FIRSTHDR (message);
176 +  for (; cmsg; cmsg = CMSG_NXTHDR (message, cmsg))
177 +    if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
178 +      nports += (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
179 +               / sizeof (int);
180 +
181 +  if (nports)
182 +    ports = __alloca (nports * sizeof (mach_port_t));
183 +
184 +  nports = 0;
185 +  for (cmsg = CMSG_FIRSTHDR (message);
186 +       cmsg;
187 +       cmsg = CMSG_NXTHDR (message, cmsg))
188 +    {
189 +      if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
190 +       {
191 +         fds = (int *) CMSG_DATA (cmsg);
192 +         nfds = (cmsg->cmsg_len - CMSG_ALIGN (sizeof (struct cmsghdr)))
193 +                / sizeof (int);
194 +
195 +         for (i = 0; i < nfds; i++)
196 +           {
197 +             err = HURD_DPORT_USE
198 +               (fds[i],
199 +                ({
200 +                  err = __io_restrict_auth (port, &ports[nports],
201 +                                            0, 0, 0, 0);
202 +                  if (! err)
203 +                    nports++;
204 +                  /* We pass the flags in the control data.  */
205 +                  fds[i] = descriptor->flags;
206 +                }));
207 +
208 +             if (err)
209 +               goto out;
210 +           }
211 +       }
212 +    }
213 +
214    if (addr)
215      {
216        if (addr->sun_family == AF_LOCAL)
217 @@ -110,9 +155,8 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
218           file_t file = __file_name_lookup (addr->sun_path, 0, 0);
219           if (file == MACH_PORT_NULL)
220             {
221 -             if (dealloc)
222 -               __vm_deallocate (__mach_task_self (), data.addr, len);
223 -             return -1;
224 +             err = errno;
225 +             goto out;
226             }
227           err = __ifsock_getsockaddr (file, &aport);
228           __mach_port_deallocate (__mach_task_self (), file);
229 @@ -120,11 +164,7 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
230             /* The file did not grok the ifsock protocol.  */
231             err = ENOTSOCK;
232           if (err)
233 -           {
234 -             if (dealloc)
235 -               __vm_deallocate (__mach_task_self (), data.addr, len);
236 -             return __hurd_fail (err);
237 -           }
238 +           goto out;
239         }
240        else
241         err = EIEIO;
242 @@ -143,8 +183,9 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
243                               /* Send the data.  */
244                               err = __socket_send (port, aport,
245                                                    flags, data.ptr, len,
246 -                                                  NULL,
247 -                                                  MACH_MSG_TYPE_COPY_SEND, 0,
248 +                                                  ports,
249 +                                                  MACH_MSG_TYPE_COPY_SEND,
250 +                                                  nports,
251                                                    message->msg_control,
252                                                    message->msg_controllen,
253                                                    &amount);
254 @@ -153,11 +194,19 @@ __libc_sendmsg (int fd, const struct msghdr *message, int flags)
255                             }
256                           err;
257                         }));
258 +  socketrpc = 1;
259 +
260 + out:
261 +  for (i = 0; i < nports; i++)
262 +    __mach_port_deallocate (__mach_task_self (), ports[i]);
263  
264    if (dealloc)
265      __vm_deallocate (__mach_task_self (), data.addr, len);
266  
267 -  return err ? __hurd_sockfail (fd, flags, err) : amount;
268 +  if (socketrpc)
269 +    return err ? __hurd_sockfail (fd, flags, err) : amount;
270 +  else
271 +    return __hurd_fail (err);
272  }
273  
274  weak_alias (__libc_sendmsg, sendmsg)