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