Update install.texi, and regenerate INSTALL.
[glibc.git] / sunrpc / svc_unix.c
blob679fbe9cb69587bddafc55c7f4105993c9d9f4c2
1 /*
2 * svc_unix.c, Server side for TCP/IP based RPC.
4 * Copyright (C) 2012-2021 Free Software Foundation, Inc.
5 * This file is part of the GNU C Library.
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.
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.
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/>.
21 * Copyright (c) 2010, Oracle America, Inc.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions are
25 * met:
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.
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.
50 * Actually implements two flavors of transporter -
51 * a unix rendezvouser (a listener and connection establisher)
52 * and a record/unix stream.
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>
70 * Ops vector for AF_UNIX based rpc service handle
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 *);
79 static const struct xp_ops svcunix_op =
81 svcunix_recv,
82 svcunix_stat,
83 svcunix_getargs,
84 svcunix_reply,
85 svcunix_freeargs,
86 svcunix_destroy
90 * Ops vector for AF_UNIX rendezvous handler
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__));
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)
101 abort ();
104 static const struct xp_ops svcunix_rendezvous_op =
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
114 static int readunix (char*, char *, int);
115 static int writeunix (char *, char *, int);
116 static SVCXPRT *makefd_xprt (int, u_int, u_int);
118 struct unix_rendezvous { /* kept in xprt->xp_p1 */
119 u_int sendsize;
120 u_int recvsize;
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];
131 * Usage:
132 * xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
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.
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.
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.
150 SVCXPRT *
151 svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
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);
159 if (sock == RPC_ANYSOCK)
161 if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
163 perror (_("svc_unix.c - AF_UNIX socket creation problem"));
164 return (SVCXPRT *) NULL;
166 madesock = TRUE;
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);
174 __bind (sock, (struct sockaddr *) &addr, len);
176 if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0
177 || __listen (sock, SOMAXCONN) != 0)
179 perror (_("svc_unix.c - cannot getsockname or listen"));
180 if (madesock)
181 __close (sock);
182 return (SVCXPRT *) NULL;
185 r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
186 xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
187 if (r == NULL || xprt == NULL)
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;
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;
205 libc_hidden_nolink_sunrpc (svcunix_create, GLIBC_2_1)
208 * Like svunix_create(), except the routine takes any *open* UNIX file
209 * descriptor as its first input.
211 SVCXPRT *
212 svcunixfd_create (int fd, u_int sendsize, u_int recvsize)
214 return makefd_xprt (fd, sendsize, recvsize);
216 libc_hidden_nolink_sunrpc (svcunixfd_create, GLIBC_2_1)
218 static SVCXPRT *
219 makefd_xprt (int fd, u_int sendsize, u_int recvsize)
221 SVCXPRT *xprt;
222 struct unix_conn *cd;
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)
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;
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;
248 static bool_t
249 rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
251 int sock;
252 struct unix_rendezvous *r;
253 struct sockaddr_un addr;
254 struct sockaddr_in in_addr;
255 socklen_t len;
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)
262 if (errno == EINTR)
263 goto again;
264 __svc_accept_failed ();
265 return FALSE;
268 * make a new transporter (re-uses xprt)
270 memset (&in_addr, '\0', sizeof (in_addr));
271 in_addr.sin_family = AF_UNIX;
272 xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
274 /* If we are out of memory, makefd_xprt has already dumped an error. */
275 if (xprt == NULL)
277 __svc_wait_on_error ();
278 return FALSE;
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 */
286 static enum xprt_stat
287 rendezvous_stat (SVCXPRT *xprt)
289 return XPRT_IDLE;
292 static void
293 svcunix_destroy (SVCXPRT *xprt)
295 struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
297 xprt_unregister (xprt);
298 __close (xprt->xp_sock);
299 if (xprt->xp_port != 0)
301 /* a rendezvouser socket */
302 xprt->xp_port = 0;
304 else
306 /* an actual connection socket */
307 XDR_DESTROY (&(cd->xdrs));
309 mem_free ((caddr_t) cd, sizeof (struct unix_conn));
310 mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
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))];
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
327 static int
328 __msgread (int sock, void *data, size_t cnt)
330 struct iovec iov;
331 struct msghdr msg;
332 int len;
334 iov.iov_base = data;
335 iov.iov_len = cnt;
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;
347 #ifdef SO_PASSCRED
349 int on = 1;
350 if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
351 return -1;
353 #endif
355 restart:
356 len = __recvmsg (sock, &msg, 0);
357 if (len >= 0)
359 if (msg.msg_flags & MSG_CTRUNC || len == 0)
360 return 0;
361 else
362 return len;
364 if (errno == EINTR)
365 goto restart;
366 return -1;
369 static int
370 __msgwrite (int sock, void *data, size_t cnt)
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;
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 ();
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);
395 iov.iov_base = data;
396 iov.iov_len = cnt;
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;
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;
414 #endif
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.)
422 static int
423 readunix (char *xprtptr, char *buf, int len)
425 SVCXPRT *xprt = (SVCXPRT *) xprtptr;
426 int sock = xprt->xp_sock;
427 int milliseconds = 35 * 1000;
428 struct pollfd pollfd;
432 pollfd.fd = sock;
433 pollfd.events = POLLIN;
434 switch (__poll (&pollfd, 1, milliseconds))
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;
449 while ((pollfd.revents & POLLIN) == 0);
451 if ((len = __msgread (sock, buf, len)) > 0)
452 return len;
454 fatal_err:
455 ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
456 return -1;
460 * writes data to the unix connection.
461 * Any error is fatal and the connection is closed.
463 static int
464 writeunix (char *xprtptr, char * buf, int len)
466 SVCXPRT *xprt = (SVCXPRT *) xprtptr;
467 int i, cnt;
469 for (cnt = len; cnt > 0; cnt -= i, buf += i)
471 if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
473 ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
474 return -1;
477 return len;
480 static enum xprt_stat
481 svcunix_stat (SVCXPRT *xprt)
483 struct unix_conn *cd =
484 (struct unix_conn *) (xprt->xp_p1);
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;
493 static bool_t
494 svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
496 struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
497 XDR *xdrs = &(cd->xdrs);
499 xdrs->x_op = XDR_DECODE;
500 xdrrec_skiprecord (xdrs);
501 if (xdr_callmsg (xdrs, msg))
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;
512 cd->strm_stat = XPRT_DIED; /* XXXX */
513 return FALSE;
516 static bool_t
517 svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
519 return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
520 args_ptr);
523 static bool_t
524 svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
526 XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
528 xdrs->x_op = XDR_FREE;
529 return (*xdr_args) (xdrs, args_ptr);
532 static bool_t
533 svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg)
535 struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
536 XDR *xdrs = &(cd->xdrs);
537 bool_t stat;
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;