1 /*
2  * svc_unix.c, Server side for TCP/IP based RPC.
3  *
4  * Copyright (C) 2012-2021 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  * <https://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
svcunix_rendezvous_abort(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);
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 *
svcunix_create(int sock,u_int sendsize,u_int recvsize,char * path)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 }
libc_hidden_nolink_sunrpc(svcunix_create,GLIBC_2_1)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 }
libc_hidden_nolink_sunrpc(svcunixfd_create,GLIBC_2_1)216 libc_hidden_nolink_sunrpc (svcunixfd_create, GLIBC_2_1)
217 
218 static SVCXPRT *
219 makefd_xprt (int fd, u_int sendsize, u_int recvsize)
220 {
221   SVCXPRT *xprt;
222   struct unix_conn *cd;
223 
224   xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
225   cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
226   if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL)
227     {
228       (void) __fxprintf (NULL, "%s: %s", "svc_unix: makefd_xprt",
229 			 _("out of memory\n"));
230       mem_free (xprt, sizeof (SVCXPRT));
231       mem_free (cd, sizeof (struct unix_conn));
232       return NULL;
233     }
234   cd->strm_stat = XPRT_IDLE;
235   xdrrec_create (&(cd->xdrs), sendsize, recvsize,
236 		 (caddr_t) xprt, readunix, writeunix);
237   xprt->xp_p2 = NULL;
238   xprt->xp_p1 = (caddr_t) cd;
239   xprt->xp_verf.oa_base = cd->verf_body;
240   xprt->xp_addrlen = 0;
241   xprt->xp_ops = &svcunix_op;	/* truly deals with calls */
242   xprt->xp_port = 0;		/* this is a connection, not a rendezvouser */
243   xprt->xp_sock = fd;
244   xprt_register (xprt);
245   return xprt;
246 }
247 
248 static bool_t
rendezvous_request(SVCXPRT * xprt,struct rpc_msg * errmsg)249 rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
250 {
251   int sock;
252   struct unix_rendezvous *r;
253   struct sockaddr_un addr;
254   struct sockaddr_in in_addr;
255   socklen_t len;
256 
257   r = (struct unix_rendezvous *) xprt->xp_p1;
258 again:
259   len = sizeof (struct sockaddr_un);
260   if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
261     {
262       if (errno == EINTR)
263 	goto again;
264       __svc_accept_failed ();
265       return FALSE;
266     }
267   /*
268    * make a new transporter (re-uses xprt)
269    */
270   memset (&in_addr, '\0', sizeof (in_addr));
271   in_addr.sin_family = AF_UNIX;
272   xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
273 
274   /* If we are out of memory, makefd_xprt has already dumped an error.  */
275   if (xprt == NULL)
276     {
277       __svc_wait_on_error ();
278       return FALSE;
279     }
280 
281   memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr));
282   xprt->xp_addrlen = len;
283   return FALSE;		/* there is never an rpc msg to be processed */
284 }
285 
286 static enum xprt_stat
rendezvous_stat(SVCXPRT * xprt)287 rendezvous_stat (SVCXPRT *xprt)
288 {
289   return XPRT_IDLE;
290 }
291 
292 static void
svcunix_destroy(SVCXPRT * xprt)293 svcunix_destroy (SVCXPRT *xprt)
294 {
295   struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
296 
297   xprt_unregister (xprt);
298   __close (xprt->xp_sock);
299   if (xprt->xp_port != 0)
300     {
301       /* a rendezvouser socket */
302       xprt->xp_port = 0;
303     }
304   else
305     {
306       /* an actual connection socket */
307       XDR_DESTROY (&(cd->xdrs));
308     }
309   mem_free ((caddr_t) cd, sizeof (struct unix_conn));
310   mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
311 }
312 
313 #ifdef SCM_CREDENTIALS
314 struct cmessage {
315   struct cmsghdr cmsg;
316   struct ucred cmcred;
317   /* hack to make sure we have enough memory */
318   char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
319 };
320 
321 /* XXX This is not thread safe, but since the main functions in svc.c
322    and the rpcgen generated *_svc functions for the daemon are also not
323    thread safe and uses static global variables, it doesn't matter. */
324 static struct cmessage cm;
325 #endif
326 
327 static int
__msgread(int sock,void * data,size_t cnt)328 __msgread (int sock, void *data, size_t cnt)
329 {
330   struct iovec iov;
331   struct msghdr msg;
332   int len;
333 
334   iov.iov_base = data;
335   iov.iov_len = cnt;
336 
337   msg.msg_iov = &iov;
338   msg.msg_iovlen = 1;
339   msg.msg_name = NULL;
340   msg.msg_namelen = 0;
341 #ifdef SCM_CREDENTIALS
342   msg.msg_control = (caddr_t) &cm;
343   msg.msg_controllen = sizeof (struct cmessage);
344 #endif
345   msg.msg_flags = 0;
346 
347 #ifdef SO_PASSCRED
348   {
349     int on = 1;
350     if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
351       return -1;
352   }
353 #endif
354 
355  restart:
356   len = __recvmsg (sock, &msg, 0);
357   if (len >= 0)
358     {
359       if (msg.msg_flags & MSG_CTRUNC || len == 0)
360 	return 0;
361       else
362 	return len;
363     }
364   if (errno == EINTR)
365     goto restart;
366   return -1;
367 }
368 
369 static int
__msgwrite(int sock,void * data,size_t cnt)370 __msgwrite (int sock, void *data, size_t cnt)
371 {
372 #ifndef SCM_CREDENTIALS
373   /* We cannot implement this reliably.  */
374   __set_errno (ENOSYS);
375   return -1;
376 #else
377   struct iovec iov;
378   struct msghdr msg;
379   struct cmsghdr *cmsg = &cm.cmsg;
380   struct ucred cred;
381   int len;
382 
383   /* XXX I'm not sure, if gete?id() is always correct, or if we should use
384      get?id(). But since keyserv needs geteuid(), we have no other chance.
385      It would be much better, if the kernel could pass both to the server. */
386   cred.pid = __getpid ();
387   cred.uid = __geteuid ();
388   cred.gid = __getegid ();
389 
390   memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
391   cmsg->cmsg_level = SOL_SOCKET;
392   cmsg->cmsg_type = SCM_CREDENTIALS;
393   cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
394 
395   iov.iov_base = data;
396   iov.iov_len = cnt;
397 
398   msg.msg_iov = &iov;
399   msg.msg_iovlen = 1;
400   msg.msg_name = NULL;
401   msg.msg_namelen = 0;
402   msg.msg_control = cmsg;
403   msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
404   msg.msg_flags = 0;
405 
406  restart:
407   len = __sendmsg (sock, &msg, 0);
408   if (len >= 0)
409     return len;
410   if (errno == EINTR)
411     goto restart;
412   return -1;
413 
414 #endif
415 }
416 
417 /*
418  * reads data from the unix connection.
419  * any error is fatal and the connection is closed.
420  * (And a read of zero bytes is a half closed stream => error.)
421  */
422 static int
readunix(char * xprtptr,char * buf,int len)423 readunix (char *xprtptr, char *buf, int len)
424 {
425   SVCXPRT *xprt = (SVCXPRT *) xprtptr;
426   int sock = xprt->xp_sock;
427   int milliseconds = 35 * 1000;
428   struct pollfd pollfd;
429 
430   do
431     {
432       pollfd.fd = sock;
433       pollfd.events = POLLIN;
434       switch (__poll (&pollfd, 1, milliseconds))
435 	{
436 	case -1:
437 	  if (errno == EINTR)
438 	    continue;
439 	  /*FALLTHROUGH*/
440 	case 0:
441 	  goto fatal_err;
442 	default:
443 	  if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
444 	      || (pollfd.revents & POLLNVAL))
445 	    goto fatal_err;
446 	  break;
447 	}
448     }
449   while ((pollfd.revents & POLLIN) == 0);
450 
451   if ((len = __msgread (sock, buf, len)) > 0)
452     return len;
453 
454  fatal_err:
455   ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
456   return -1;
457 }
458 
459 /*
460  * writes data to the unix connection.
461  * Any error is fatal and the connection is closed.
462  */
463 static int
writeunix(char * xprtptr,char * buf,int len)464 writeunix (char *xprtptr, char * buf, int len)
465 {
466   SVCXPRT *xprt = (SVCXPRT *) xprtptr;
467   int i, cnt;
468 
469   for (cnt = len; cnt > 0; cnt -= i, buf += i)
470     {
471       if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
472 	{
473 	  ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
474 	  return -1;
475 	}
476     }
477   return len;
478 }
479 
480 static enum xprt_stat
svcunix_stat(SVCXPRT * xprt)481 svcunix_stat (SVCXPRT *xprt)
482 {
483   struct unix_conn *cd =
484   (struct unix_conn *) (xprt->xp_p1);
485 
486   if (cd->strm_stat == XPRT_DIED)
487     return XPRT_DIED;
488   if (!xdrrec_eof (&(cd->xdrs)))
489     return XPRT_MOREREQS;
490   return XPRT_IDLE;
491 }
492 
493 static bool_t
svcunix_recv(SVCXPRT * xprt,struct rpc_msg * msg)494 svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
495 {
496   struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
497   XDR *xdrs = &(cd->xdrs);
498 
499   xdrs->x_op = XDR_DECODE;
500   xdrrec_skiprecord (xdrs);
501   if (xdr_callmsg (xdrs, msg))
502     {
503       cd->x_id = msg->rm_xid;
504       /* set up verifiers */
505 #ifdef SCM_CREDENTIALS
506       msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
507       msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
508       msg->rm_call.cb_verf.oa_length = sizeof (cm);
509 #endif
510       return TRUE;
511     }
512   cd->strm_stat = XPRT_DIED;	/* XXXX */
513   return FALSE;
514 }
515 
516 static bool_t
svcunix_getargs(SVCXPRT * xprt,xdrproc_t xdr_args,caddr_t args_ptr)517 svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
518 {
519   return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
520 		      args_ptr);
521 }
522 
523 static bool_t
svcunix_freeargs(SVCXPRT * xprt,xdrproc_t xdr_args,caddr_t args_ptr)524 svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
525 {
526   XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
527 
528   xdrs->x_op = XDR_FREE;
529   return (*xdr_args) (xdrs, args_ptr);
530 }
531 
532 static bool_t
svcunix_reply(SVCXPRT * xprt,struct rpc_msg * msg)533 svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg)
534 {
535   struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
536   XDR *xdrs = &(cd->xdrs);
537   bool_t stat;
538 
539   xdrs->x_op = XDR_ENCODE;
540   msg->rm_xid = cd->x_id;
541   stat = xdr_replymsg (xdrs, msg);
542   (void) xdrrec_endofrecord (xdrs, TRUE);
543   return stat;
544 }
545