Reinitialize _create_xid state after fork.
[platform/upstream/glibc.git] / sunrpc / svc_unix.c
1 /*
2  * svc_unix.c, Server side for TCP/IP based RPC.
3  *
4  * Copyright (C) 1984, Sun Microsystems, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of Sun Microsystems, Inc. nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Actually implements two flavors of transporter -
34  * a unix rendezvouser (a listener and connection establisher)
35  * and a record/unix stream.
36  */
37
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <rpc/rpc.h>
42 #include <rpc/svc.h>
43 #include <sys/socket.h>
44 #include <sys/uio.h>
45 #include <sys/poll.h>
46 #include <errno.h>
47 #include <stdlib.h>
48 #include <libintl.h>
49
50 #ifdef USE_IN_LIBIO
51 # include <wchar.h>
52 #endif
53
54 /*
55  * Ops vector for AF_UNIX based rpc service handle
56  */
57 static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *);
58 static enum xprt_stat svcunix_stat (SVCXPRT *);
59 static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t);
60 static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *);
61 static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
62 static void svcunix_destroy (SVCXPRT *);
63
64 static const struct xp_ops svcunix_op =
65 {
66   svcunix_recv,
67   svcunix_stat,
68   svcunix_getargs,
69   svcunix_reply,
70   svcunix_freeargs,
71   svcunix_destroy
72 };
73
74 /*
75  * Ops vector for AF_UNIX rendezvous handler
76  */
77 static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
78 static enum xprt_stat rendezvous_stat (SVCXPRT *);
79 static void svcunix_rendezvous_abort (void) __attribute__ ((__noreturn__));
80
81 /* This function makes sure abort() relocation goes through PLT
82    and thus can be lazy bound.  */
83 static void
84 svcunix_rendezvous_abort (void)
85 {
86   abort ();
87 };
88
89 static const struct xp_ops svcunix_rendezvous_op =
90 {
91   rendezvous_request,
92   rendezvous_stat,
93   (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
94   (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort,
95   (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
96   svcunix_destroy
97 };
98
99 static int readunix (char*, char *, int);
100 static int writeunix (char *, char *, int);
101 static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function;
102
103 struct unix_rendezvous {        /* kept in xprt->xp_p1 */
104   u_int sendsize;
105   u_int recvsize;
106 };
107
108 struct unix_conn {              /* kept in xprt->xp_p1 */
109   enum xprt_stat strm_stat;
110   u_long x_id;
111   XDR xdrs;
112   char verf_body[MAX_AUTH_BYTES];
113 };
114
115 /*
116  * Usage:
117  *      xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
118  *
119  * Creates, registers, and returns a (rpc) unix based transporter.
120  * Once *xprt is initialized, it is registered as a transporter
121  * see (svc.h, xprt_register).  This routine returns
122  * a NULL if a problem occurred.
123  *
124  * If sock<0 then a socket is created, else sock is used.
125  * If the socket, sock is not bound to a port then svcunix_create
126  * binds it to an arbitrary port.  The routine then starts a unix
127  * listener on the socket's associated port.  In any (successful) case,
128  * xprt->xp_sock is the registered socket number and xprt->xp_port is the
129  * associated port number.
130  *
131  * Since unix streams do buffered io similar to stdio, the caller can specify
132  * how big the send and receive buffers are via the second and third parms;
133  * 0 => use the system default.
134  */
135 SVCXPRT *
136 svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
137 {
138   bool_t madesock = FALSE;
139   SVCXPRT *xprt;
140   struct unix_rendezvous *r;
141   struct sockaddr_un addr;
142   socklen_t len = sizeof (struct sockaddr_in);
143
144   if (sock == RPC_ANYSOCK)
145     {
146       if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
147         {
148           perror (_("svc_unix.c - AF_UNIX socket creation problem"));
149           return (SVCXPRT *) NULL;
150         }
151       madesock = TRUE;
152     }
153   memset (&addr, '\0', sizeof (addr));
154   addr.sun_family = AF_UNIX;
155   len = strlen (path) + 1;
156   memcpy (addr.sun_path, path, len);
157   len += sizeof (addr.sun_family);
158
159   __bind (sock, (struct sockaddr *) &addr, len);
160
161   if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0
162       || __listen (sock, SOMAXCONN) != 0)
163     {
164       perror (_("svc_unix.c - cannot getsockname or listen"));
165       if (madesock)
166         __close (sock);
167       return (SVCXPRT *) NULL;
168     }
169
170   r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
171   xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
172   if (r == NULL || xprt == NULL)
173     {
174       __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
175       mem_free (r, sizeof (*r));
176       mem_free (xprt, sizeof (SVCXPRT));
177       return NULL;
178     }
179   r->sendsize = sendsize;
180   r->recvsize = recvsize;
181   xprt->xp_p2 = NULL;
182   xprt->xp_p1 = (caddr_t) r;
183   xprt->xp_verf = _null_auth;
184   xprt->xp_ops = &svcunix_rendezvous_op;
185   xprt->xp_port = -1;
186   xprt->xp_sock = sock;
187   xprt_register (xprt);
188   return xprt;
189 }
190
191 /*
192  * Like svunix_create(), except the routine takes any *open* UNIX file
193  * descriptor as its first input.
194  */
195 SVCXPRT *
196 svcunixfd_create (int fd, u_int sendsize, u_int recvsize)
197 {
198   return makefd_xprt (fd, sendsize, recvsize);
199 }
200
201 static SVCXPRT *
202 internal_function
203 makefd_xprt (int fd, u_int sendsize, u_int recvsize)
204 {
205   SVCXPRT *xprt;
206   struct unix_conn *cd;
207
208   xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
209   cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
210   if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL)
211     {
212       (void) __fxprintf (NULL, "%s: %s", "svc_unix: makefd_xprt",
213                          _("out of memory\n"));
214       mem_free (xprt, sizeof (SVCXPRT));
215       mem_free (cd, sizeof (struct unix_conn));
216       return NULL;
217     }
218   cd->strm_stat = XPRT_IDLE;
219   INTUSE(xdrrec_create) (&(cd->xdrs), sendsize, recvsize,
220                          (caddr_t) xprt, readunix, writeunix);
221   xprt->xp_p2 = NULL;
222   xprt->xp_p1 = (caddr_t) cd;
223   xprt->xp_verf.oa_base = cd->verf_body;
224   xprt->xp_addrlen = 0;
225   xprt->xp_ops = &svcunix_op;   /* truly deals with calls */
226   xprt->xp_port = 0;            /* this is a connection, not a rendezvouser */
227   xprt->xp_sock = fd;
228   xprt_register (xprt);
229   return xprt;
230 }
231
232 static bool_t
233 rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
234 {
235   int sock;
236   struct unix_rendezvous *r;
237   struct sockaddr_un addr;
238   struct sockaddr_in in_addr;
239   socklen_t len;
240
241   r = (struct unix_rendezvous *) xprt->xp_p1;
242 again:
243   len = sizeof (struct sockaddr_un);
244   if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
245     {
246       if (errno == EINTR)
247         goto again;
248       return FALSE;
249     }
250   /*
251    * make a new transporter (re-uses xprt)
252    */
253   memset (&in_addr, '\0', sizeof (in_addr));
254   in_addr.sin_family = AF_UNIX;
255   xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
256   memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr));
257   xprt->xp_addrlen = len;
258   return FALSE;         /* there is never an rpc msg to be processed */
259 }
260
261 static enum xprt_stat
262 rendezvous_stat (SVCXPRT *xprt)
263 {
264   return XPRT_IDLE;
265 }
266
267 static void
268 svcunix_destroy (SVCXPRT *xprt)
269 {
270   struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
271
272   xprt_unregister (xprt);
273   __close (xprt->xp_sock);
274   if (xprt->xp_port != 0)
275     {
276       /* a rendezvouser socket */
277       xprt->xp_port = 0;
278     }
279   else
280     {
281       /* an actual connection socket */
282       XDR_DESTROY (&(cd->xdrs));
283     }
284   mem_free ((caddr_t) cd, sizeof (struct unix_conn));
285   mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
286 }
287
288 #ifdef SCM_CREDENTIALS
289 struct cmessage {
290   struct cmsghdr cmsg;
291   struct ucred cmcred;
292   /* hack to make sure we have enough memory */
293   char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
294 };
295
296 /* XXX This is not thread safe, but since the main functions in svc.c
297    and the rpcgen generated *_svc functions for the daemon are also not
298    thread safe and uses static global variables, it doesn't matter. */
299 static struct cmessage cm;
300 #endif
301
302 static int
303 __msgread (int sock, void *data, size_t cnt)
304 {
305   struct iovec iov;
306   struct msghdr msg;
307   int len;
308
309   iov.iov_base = data;
310   iov.iov_len = cnt;
311
312   msg.msg_iov = &iov;
313   msg.msg_iovlen = 1;
314   msg.msg_name = NULL;
315   msg.msg_namelen = 0;
316 #ifdef SCM_CREDENTIALS
317   msg.msg_control = (caddr_t) &cm;
318   msg.msg_controllen = sizeof (struct cmessage);
319 #endif
320   msg.msg_flags = 0;
321
322 #ifdef SO_PASSCRED
323   {
324     int on = 1;
325     if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
326       return -1;
327   }
328 #endif
329
330  restart:
331   len = __recvmsg (sock, &msg, 0);
332   if (len >= 0)
333     {
334       if (msg.msg_flags & MSG_CTRUNC || len == 0)
335         return 0;
336       else
337         return len;
338     }
339   if (errno == EINTR)
340     goto restart;
341   return -1;
342 }
343
344 static int
345 __msgwrite (int sock, void *data, size_t cnt)
346 {
347 #ifndef SCM_CREDENTIALS
348   /* We cannot implement this reliably.  */
349   __set_errno (ENOSYS);
350   return -1;
351 #else
352   struct iovec iov;
353   struct msghdr msg;
354   struct cmsghdr *cmsg = &cm.cmsg;
355   struct ucred cred;
356   int len;
357
358   /* XXX I'm not sure, if gete?id() is always correct, or if we should use
359      get?id(). But since keyserv needs geteuid(), we have no other chance.
360      It would be much better, if the kernel could pass both to the server. */
361   cred.pid = __getpid ();
362   cred.uid = __geteuid ();
363   cred.gid = __getegid ();
364
365   memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
366   cmsg->cmsg_level = SOL_SOCKET;
367   cmsg->cmsg_type = SCM_CREDENTIALS;
368   cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
369
370   iov.iov_base = data;
371   iov.iov_len = cnt;
372
373   msg.msg_iov = &iov;
374   msg.msg_iovlen = 1;
375   msg.msg_name = NULL;
376   msg.msg_namelen = 0;
377   msg.msg_control = cmsg;
378   msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
379   msg.msg_flags = 0;
380
381  restart:
382   len = __sendmsg (sock, &msg, 0);
383   if (len >= 0)
384     return len;
385   if (errno == EINTR)
386     goto restart;
387   return -1;
388
389 #endif
390 }
391
392 /*
393  * reads data from the unix connection.
394  * any error is fatal and the connection is closed.
395  * (And a read of zero bytes is a half closed stream => error.)
396  */
397 static int
398 readunix (char *xprtptr, char *buf, int len)
399 {
400   SVCXPRT *xprt = (SVCXPRT *) xprtptr;
401   int sock = xprt->xp_sock;
402   int milliseconds = 35 * 1000;
403   struct pollfd pollfd;
404
405   do
406     {
407       pollfd.fd = sock;
408       pollfd.events = POLLIN;
409       switch (__poll (&pollfd, 1, milliseconds))
410         {
411         case -1:
412           if (errno == EINTR)
413             continue;
414           /*FALLTHROUGH*/
415         case 0:
416           goto fatal_err;
417         default:
418           if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
419               || (pollfd.revents & POLLNVAL))
420             goto fatal_err;
421           break;
422         }
423     }
424   while ((pollfd.revents & POLLIN) == 0);
425
426   if ((len = __msgread (sock, buf, len)) > 0)
427     return len;
428
429  fatal_err:
430   ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
431   return -1;
432 }
433
434 /*
435  * writes data to the unix connection.
436  * Any error is fatal and the connection is closed.
437  */
438 static int
439 writeunix (char *xprtptr, char * buf, int len)
440 {
441   SVCXPRT *xprt = (SVCXPRT *) xprtptr;
442   int i, cnt;
443
444   for (cnt = len; cnt > 0; cnt -= i, buf += i)
445     {
446       if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
447         {
448           ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
449           return -1;
450         }
451     }
452   return len;
453 }
454
455 static enum xprt_stat
456 svcunix_stat (SVCXPRT *xprt)
457 {
458   struct unix_conn *cd =
459   (struct unix_conn *) (xprt->xp_p1);
460
461   if (cd->strm_stat == XPRT_DIED)
462     return XPRT_DIED;
463   if (!INTUSE(xdrrec_eof) (&(cd->xdrs)))
464     return XPRT_MOREREQS;
465   return XPRT_IDLE;
466 }
467
468 static bool_t
469 svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
470 {
471   struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
472   XDR *xdrs = &(cd->xdrs);
473
474   xdrs->x_op = XDR_DECODE;
475   INTUSE(xdrrec_skiprecord) (xdrs);
476   if (INTUSE(xdr_callmsg) (xdrs, msg))
477     {
478       cd->x_id = msg->rm_xid;
479       /* set up verifiers */
480 #ifdef SCM_CREDENTIALS
481       msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
482       msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
483       msg->rm_call.cb_verf.oa_length = sizeof (cm);
484 #endif
485       return TRUE;
486     }
487   cd->strm_stat = XPRT_DIED;    /* XXXX */
488   return FALSE;
489 }
490
491 static bool_t
492 svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
493 {
494   return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
495                       args_ptr);
496 }
497
498 static bool_t
499 svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
500 {
501   XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
502
503   xdrs->x_op = XDR_FREE;
504   return (*xdr_args) (xdrs, args_ptr);
505 }
506
507 static bool_t
508 svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg)
509 {
510   struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
511   XDR *xdrs = &(cd->xdrs);
512   bool_t stat;
513
514   xdrs->x_op = XDR_ENCODE;
515   msg->rm_xid = cd->x_id;
516   stat = INTUSE(xdr_replymsg) (xdrs, msg);
517   (void) INTUSE(xdrrec_endofrecord) (xdrs, TRUE);
518   return stat;
519 }