1 /* UNIX Domain Sockets - uds.c - socket management */
2
3 #include "uds.h"
4
5 static struct udssock uds_array[NR_UDSSOCK];
6 static TAILQ_HEAD(uds_freelist, udssock) uds_freelist;
7 static unsigned int uds_in_use;
8 static int uds_running;
9
10 static const struct sockevent_ops uds_ops;
11
SLIST_HEAD(udshash,udssock)12 static SLIST_HEAD(udshash, udssock) udshash[UDSHASH_SLOTS];
13
14 /*
15 * Initialize file-to-socket hash table.
16 */
17 static void
18 udshash_init(void)
19 {
20 unsigned int slot;
21
22 for (slot = 0; slot < __arraycount(udshash); slot++)
23 SLIST_INIT(&udshash[slot]);
24 }
25
26 /*
27 * Return a hash table slot number for the given <dev,ino> pair.
28 */
29 static unsigned int
udshash_slot(dev_t dev,ino_t ino)30 udshash_slot(dev_t dev, ino_t ino)
31 {
32
33 assert(dev != NO_DEV);
34 assert(ino != 0);
35
36 /*
37 * Effectively combining two 64-bit numbers into a single 6-or-so-bit
38 * hash is not too easy. This hash function is probably among the
39 * worst options. Then again it is not all that critical as we are not
40 * expecting that many bound UDS sockets in the system anyway.
41 */
42 return (unsigned int)(dev ^ ino) % UDSHASH_SLOTS;
43 }
44
45 /*
46 * Look for a socket that is bound to the given <dev,ino> pair. Return a
47 * pointer to the socket if found, or NULL otherwise.
48 */
49 static struct udssock *
udshash_get(dev_t dev,ino_t ino)50 udshash_get(dev_t dev, ino_t ino)
51 {
52 struct udssock *uds;
53 unsigned int slot;
54
55 slot = udshash_slot(dev, ino);
56
57 SLIST_FOREACH(uds, &udshash[slot], uds_hash) {
58 if (uds->uds_dev == dev && uds->uds_ino == ino)
59 return uds;
60 }
61
62 return NULL;
63 }
64
65 /*
66 * Add a socket to the file-to-socket hash table. The socket must have its
67 * device and inode fields set, and must not be in the hash table already.
68 */
69 static void
udshash_add(struct udssock * uds)70 udshash_add(struct udssock * uds)
71 {
72 unsigned int slot;
73
74 slot = udshash_slot(uds->uds_dev, uds->uds_ino);
75
76 SLIST_INSERT_HEAD(&udshash[slot], uds, uds_hash);
77 }
78
79 /*
80 * Remove a socket from the file-to-socket hash table. The socket must be in
81 * the hash table.
82 */
83 static void
udshash_del(struct udssock * uds)84 udshash_del(struct udssock * uds)
85 {
86 unsigned int slot;
87
88 slot = udshash_slot(uds->uds_dev, uds->uds_ino);
89
90 /* This macro is O(n). */
91 SLIST_REMOVE(&udshash[slot], uds, udssock, uds_hash);
92 }
93
94 /*
95 * Return the socket identifier for the given UDS socket object.
96 */
97 sockid_t
uds_get_id(struct udssock * uds)98 uds_get_id(struct udssock * uds)
99 {
100
101 return (sockid_t)(uds - uds_array);
102 }
103
104 /*
105 * Given either NULL or a previously returned socket, return the next in-use
106 * UDS socket of the given socket type, or NULL if there are no more matches.
107 * The sockets are returned in random order, but each matching socket is
108 * returned exactly once (until any socket is allocated or freed).
109 */
110 struct udssock *
uds_enum(struct udssock * prev,int type)111 uds_enum(struct udssock * prev, int type)
112 {
113 sockid_t id;
114
115 if (prev != NULL)
116 id = uds_get_id(prev) + 1;
117 else
118 id = 0;
119
120 for (; id < NR_UDSSOCK; id++)
121 if ((uds_array[id].uds_flags & UDSF_IN_USE) &&
122 uds_get_type(&uds_array[id]) == type)
123 return &uds_array[id];
124
125 return NULL;
126 }
127
128 /*
129 * Invalidate credentials on the socket.
130 */
131 static void
uds_clear_cred(struct udssock * uds)132 uds_clear_cred(struct udssock * uds)
133 {
134
135 uds->uds_cred.unp_pid = -1;
136 uds->uds_cred.unp_euid = -1;
137 uds->uds_cred.unp_egid = -1;
138 }
139
140 /*
141 * Obtain the credentials (process, user, and group ID) of the given user
142 * endpoint and associate them with the socket for later retrieval. It is
143 * important to note that this information is obtained once at connect time,
144 * and never updated later. The party receiving the credentials must take this
145 * into account.
146 */
147 static void
uds_get_cred(struct udssock * uds,endpoint_t user_endpt)148 uds_get_cred(struct udssock * uds, endpoint_t user_endpt)
149 {
150 int r;
151
152 if ((uds->uds_cred.unp_pid = r = getepinfo(user_endpt,
153 &uds->uds_cred.unp_euid, &uds->uds_cred.unp_egid)) < 0) {
154 printf("UDS: failed obtaining credentials of %d (%d)\n",
155 user_endpt, r);
156
157 uds_clear_cred(uds);
158 }
159 }
160
161 /*
162 * Allocate and initialize a UDS socket. On succes, return OK with a pointer
163 * to the new socket in 'udsp'. On failure, return a negative error code.
164 */
165 static int
uds_alloc(struct udssock ** udsp)166 uds_alloc(struct udssock ** udsp)
167 {
168 struct udssock *uds;
169 int r;
170
171 /* Allocate, initialize, and return a UNIX domain socket object. */
172 if (TAILQ_EMPTY(&uds_freelist))
173 return ENOBUFS;
174
175 uds = TAILQ_FIRST(&uds_freelist);
176
177 uds->uds_conn = NULL; /* not connected */
178 uds->uds_link = NULL; /* not connecting or linked */
179 uds->uds_queued = 0;
180 uds->uds_flags = UDSF_IN_USE; /* may be found through enumeration */
181 uds->uds_pathlen = 0; /* not bound: no path */
182 uds->uds_dev = NO_DEV; /* not hashed: no socket file device */
183 uds->uds_ino = 0; /* not hashed: no socket file inode */
184 uds_clear_cred(uds); /* no bind/connect-time credentials */
185 TAILQ_INIT(&uds->uds_queue); /* an empty queue */
186
187 if ((r = uds_io_setup(uds)) != OK)
188 return r;
189
190 TAILQ_REMOVE(&uds_freelist, uds, uds_next);
191
192 assert(uds_in_use < NR_UDSSOCK);
193 uds_in_use++;
194
195 *udsp = uds;
196 return OK;
197 }
198
199 /*
200 * Free a previously allocated socket.
201 */
202 static void
uds_free(struct sock * sock)203 uds_free(struct sock * sock)
204 {
205 struct udssock *uds = (struct udssock *)sock;
206
207 uds_io_cleanup(uds);
208
209 uds->uds_flags = 0; /* no longer in use */
210
211 TAILQ_INSERT_HEAD(&uds_freelist, uds, uds_next);
212
213 assert(uds_in_use > 0);
214 if (--uds_in_use == 0 && uds_running == FALSE)
215 sef_cancel();
216 }
217
218 /*
219 * Create a new socket.
220 */
221 static sockid_t
uds_socket(int domain,int type,int protocol,endpoint_t user_endpt __unused,struct sock ** sockp,const struct sockevent_ops ** ops)222 uds_socket(int domain, int type, int protocol, endpoint_t user_endpt __unused,
223 struct sock ** sockp, const struct sockevent_ops ** ops)
224 {
225 struct udssock *uds;
226 int r;
227
228 dprintf(("UDS: socket(%d,%d,%d)\n", domain, type, protocol));
229
230 if (domain != PF_UNIX) {
231 /* This means the service was configured incorrectly. */
232 printf("UDS: got request for domain %d\n", domain);
233
234 return EAFNOSUPPORT;
235 }
236
237 /* We support the following three socket types. */
238 switch (type) {
239 case SOCK_STREAM:
240 case SOCK_SEQPACKET:
241 case SOCK_DGRAM:
242 break;
243 default:
244 return EPROTOTYPE;
245 }
246
247 /*
248 * The PF_UNIX domain does not support particular protocols, so the
249 * given protocol must be zero (= anything that matches).
250 */
251 if (protocol != UDSPROTO_UDS)
252 return EPROTONOSUPPORT;
253
254 if ((r = uds_alloc(&uds)) != OK)
255 return r;
256
257 dprintf(("UDS: socket returns %d\n", uds_get_id(uds)));
258
259 *sockp = &uds->uds_sock;
260 *ops = &uds_ops;
261 return uds_get_id(uds);
262 }
263
264 /*
265 * Connect a pair of sockets.
266 */
267 static int
uds_pair(struct sock * sock1,struct sock * sock2,endpoint_t user_endpt)268 uds_pair(struct sock * sock1, struct sock * sock2, endpoint_t user_endpt)
269 {
270 struct udssock *uds1 = (struct udssock *)sock1;
271 struct udssock *uds2 = (struct udssock *)sock2;
272
273 dprintf(("UDS: pair(%d,%d)\n", uds_get_id(uds1), uds_get_id(uds2)));
274
275 /* Only connection-oriented types are acceptable. */
276 if (uds_get_type(uds1) == SOCK_DGRAM)
277 return EOPNOTSUPP;
278
279 /* Connect the sockets. */
280 uds1->uds_conn = uds2;
281 uds2->uds_conn = uds1;
282 uds1->uds_flags |= UDSF_CONNECTED;
283 uds2->uds_flags |= UDSF_CONNECTED;
284
285 /* Obtain the (same) credentials for both sides of the connection. */
286 uds_get_cred(uds1, user_endpt);
287 memcpy(&uds2->uds_cred, &uds1->uds_cred, sizeof(uds2->uds_cred));
288
289 return OK;
290 }
291
292 /*
293 * Disconnect a UDS socket, notifying or freeing up the other end of the
294 * connection depending on whether the socket was linked, that is, on the
295 * accept queue of a listening socket.
296 */
297 static void
uds_disconnect(struct udssock * uds,int was_linked)298 uds_disconnect(struct udssock * uds, int was_linked)
299 {
300 struct udssock *conn;
301
302 assert(uds_is_connected(uds));
303 assert(uds_has_conn(uds));
304
305 conn = uds->uds_conn;
306
307 assert(uds_is_connected(conn));
308 assert(uds_has_conn(conn));
309 assert(!uds_has_link(conn));
310 assert(conn->uds_conn == uds);
311
312 /* Disconnect the sockets. */
313 uds->uds_conn = NULL;
314 conn->uds_conn = NULL;
315
316 /*
317 * If the given socket is linked, then it is a connected socket for
318 * which the other end has been created but not yet accepted. In that
319 * case, the other end ('conn') will have to be freed up. Otherwise,
320 * it is a regular user-created socket and we must properly transition
321 * it into disconnected state.
322 */
323 if (!was_linked) {
324 sockevent_raise(&conn->uds_sock, SEV_SEND | SEV_RECV);
325
326 /*
327 * Clear the peer credentials so that they will not be mistaken
328 * for having been obtained at bind time.
329 */
330 uds_clear_cred(conn);
331 } else
332 sockevent_raise(&conn->uds_sock, SEV_CLOSE);
333 }
334
335 /*
336 * Add the socket 'link' to the queue of the socket 'uds'. This also implies
337 * that 'link's link socket is set to 'uds'.
338 */
339 static void
uds_add_queue(struct udssock * uds,struct udssock * link)340 uds_add_queue(struct udssock * uds, struct udssock * link)
341 {
342
343 dprintf(("UDS: add_queue(%d,%d)\n",
344 uds_get_id(uds), uds_get_id(link)));
345
346 TAILQ_INSERT_TAIL(&uds->uds_queue, link, uds_next);
347
348 uds->uds_queued++;
349 assert(uds->uds_queued != 0);
350
351 link->uds_link = uds;
352 }
353
354 /*
355 * Remove the socket 'link' from the queue of the socket 'uds'. This also
356 * reset 'link's link to NULL.
357 */
358 static void
uds_del_queue(struct udssock * uds,struct udssock * link)359 uds_del_queue(struct udssock * uds, struct udssock * link)
360 {
361
362 dprintf(("UDS: del_queue(%d,%d)\n",
363 uds_get_id(uds), uds_get_id(link)));
364
365 assert(link->uds_link == uds);
366
367 TAILQ_REMOVE(&uds->uds_queue, link, uds_next);
368
369 assert(uds->uds_queued > 0);
370 uds->uds_queued--;
371
372 link->uds_link = NULL;
373 }
374
375 /*
376 * Remove all sockets from the queue of the socket 'uds', with the exception of
377 * 'except' if non-NULL. Raise an ECONNRESET error on all removed sockets that
378 * are not equal to 'uds'.
379 */
380 static void
uds_clear_queue(struct udssock * uds,struct udssock * except)381 uds_clear_queue(struct udssock * uds, struct udssock * except)
382 {
383 struct udssock *link, *tmp;
384 int found;
385
386 dprintf(("UDS: clear_queue(%d,%d)\n",
387 uds_get_id(uds), (except != NULL) ? uds_get_id(except) : -1));
388
389 found = 0;
390
391 /*
392 * Abort all connecting sockets queued on this socket, except for the
393 * given exception, which may be NULL.
394 */
395 TAILQ_FOREACH_SAFE(link, &uds->uds_queue, uds_next, tmp) {
396 if (link == except) {
397 found++;
398
399 continue;
400 }
401
402 dprintf(("UDS: clear_queue removes %d\n", uds_get_id(link)));
403
404 assert(uds_get_type(link) == SOCK_DGRAM ||
405 uds_is_connecting(link) || uds_is_connected(link));
406
407 uds_del_queue(uds, link);
408
409 /*
410 * Generate an error only if the socket was not linked to
411 * itself (only datagram sockets can be linked to themselves).
412 * The error is not helpful for applications in that case.
413 */
414 if (uds != link)
415 sockevent_set_error(&link->uds_sock, ECONNRESET);
416
417 /*
418 * If this is a listening socket, disconnect the connecting or
419 * connected end. If a connected peer was already created for
420 * the queued socket, dispose of that peer.
421 *
422 * Clear credentials obtained when starting to connect (in
423 * which case the socket is always a connection-oriented
424 * socket), so that they will not be mistaken for credentials
425 * obtained at bind time.
426 */
427 if (uds_get_type(link) != SOCK_DGRAM) {
428 if (uds_is_connected(link))
429 uds_disconnect(link, TRUE /*was_linked*/);
430 else
431 uds_clear_cred(link);
432 }
433 }
434
435 assert(uds->uds_queued == found);
436 }
437
438 /*
439 * Check whether the socket address given in 'addr', with length 'addr_len', is
440 * a valid UNIX domain socket address (including a path to a socket file). On
441 * success, return the (non-zero) length of the socket file's path, minus the
442 * null terminator which may in fact not be present. The caller is responsible
443 * for copying and terminating the path as needed. A pointer to the path as
444 * stored in 'addr' is returned in 'pathp'. On failure, return an error code.
445 */
446 static int
uds_check_addr(const struct sockaddr * addr,socklen_t addr_len,const char ** pathp)447 uds_check_addr(const struct sockaddr * addr, socklen_t addr_len,
448 const char ** pathp)
449 {
450 const char *p;
451 size_t len;
452
453 /*
454 * We could cast to a sockaddr_un structure pointer first, but that
455 * would not provide any benefits here. Instead, we use sa_data as the
456 * generic equivalent of sun_path.
457 */
458 if (addr_len < offsetof(struct sockaddr, sa_data))
459 return EINVAL;
460
461 if (addr->sa_family != AF_UNIX)
462 return EAFNOSUPPORT;
463
464 len = (size_t)addr_len - offsetof(struct sockaddr, sa_data);
465 if (len > 0 && (p = memchr(addr->sa_data, '\0', len)) != NULL)
466 len = (size_t)(p - addr->sa_data);
467
468 /* The given path name must not be an empty string. */
469 if (len == 0)
470 return ENOENT;
471
472 /* This check should be redundant but better safe than sorry. */
473 if (len >= UDS_PATH_MAX)
474 return EINVAL;
475
476 *pathp = (const char *)addr->sa_data;
477 return len;
478 }
479
480 /*
481 * Given the socket file path given as 'path' with length 'path_len' (not
482 * necessarily null terminated), store a socket address with the path in
483 * 'addr', and return the socket address length in 'addr_len'. The calling
484 * libraries (libsockdriver, libsockevent) and the static assert in uds.h
485 * guarantee that 'addr' is sufficiently large to store any address we generate
486 * here. The libraries may subsequently copy out only a part of it to the user
487 * process. This function always succeeds.
488 */
489 void
uds_make_addr(const char * path,size_t len,struct sockaddr * addr,socklen_t * addr_len)490 uds_make_addr(const char * path, size_t len, struct sockaddr * addr,
491 socklen_t * addr_len)
492 {
493
494 /*
495 * Generate the address. The stored length (sa_len/sun_len) does not
496 * include a null terminator. The entire structure does include a null
497 * terminator, but only if the socket is bound.
498 */
499 addr->sa_len = offsetof(struct sockaddr, sa_data) + len;
500 addr->sa_family = AF_UNIX;
501 if (len > 0) {
502 /* This call may (intentionally) overrun the sa_data size. */
503 memcpy((char *)addr->sa_data, path, len);
504 ((char *)addr->sa_data)[len] = '\0';
505
506 /* The socket is bound, so include the null terminator. */
507 len++;
508 assert(len <= UDS_PATH_MAX);
509 }
510
511 /* Note that this length may be different from sa_len/sun_len now. */
512 *addr_len = offsetof(struct sockaddr, sa_data) + len;
513 }
514
515 /*
516 * Bind a socket to a local address.
517 */
518 static int
uds_bind(struct sock * sock,const struct sockaddr * addr,socklen_t addr_len,endpoint_t user_endpt)519 uds_bind(struct sock * sock, const struct sockaddr * addr, socklen_t addr_len,
520 endpoint_t user_endpt)
521 {
522 struct udssock *uds = (struct udssock *)sock;
523 struct udssock *uds2;
524 const char *path;
525 size_t len;
526 dev_t dev;
527 ino_t ino;
528 int r;
529
530 dprintf(("UDS: bind(%d)\n", uds_get_id(uds)));
531
532 /* A socket may be bound at any time, but only once. */
533 if (uds_is_bound(uds))
534 return EINVAL;
535
536 /* Verify that the user gave us an acceptable address. */
537 if ((r = uds_check_addr(addr, addr_len, &path)) < 0)
538 return r;
539 len = (size_t)r;
540
541 /* Attempt to create the socket file on the file system. */
542 r = socketpath(user_endpt, path, len, SPATH_CREATE, &dev, &ino);
543 if (r != OK)
544 return r;
545 assert(dev != NO_DEV && ino != 0);
546
547 /*
548 * It is possible that a socket file of a previously bound socket was
549 * unlinked, and due to inode number reuse, a new socket file has now
550 * been created with the same <dev,ino> pair. In that case, we must
551 * unbind the old socket, because it must no longer be found. The old
552 * socket will still have a path (and behave as though it is bound) but
553 * no longer be found through hash lookups.
554 */
555 if ((uds2 = udshash_get(dev, ino)) != NULL) {
556 udshash_del(uds2);
557
558 uds2->uds_dev = NO_DEV;
559 uds2->uds_ino = 0;
560 }
561
562 /*
563 * Obtain credentials for the socket, unless the socket is already
564 * connecting or connected, in which case we must not replace the
565 * credentials we obtained already. We later clear those credentials
566 * upon a connection failure or disconnect, so that if the socket is
567 * then put in listening mode, we know there are no bind-time
568 * credentials. Not ideal, but we really need two separate sets of
569 * credentials if we want to get this right, which is a waste of memory
570 * as no sane application writer would ever rely on credential passing
571 * after recycling a socket..
572 */
573 if (uds_get_type(uds) != SOCK_DGRAM && !uds_is_connecting(uds) &&
574 !uds_is_connected(uds))
575 uds_get_cred(uds, user_endpt);
576
577 /* Asssign the address to the socket. */
578 uds->uds_pathlen = len;
579 memcpy(&uds->uds_path, path, len);
580 uds->uds_dev = dev;
581 uds->uds_ino = ino;
582
583 udshash_add(uds);
584
585 return OK;
586 }
587
588 /*
589 * Look up a UDS socket based on a user-given address. If a socket exists for
590 * the address, check if it is type-compatible with the given UDS socket.
591 * On succes, return OK, with 'peerp' set to the socket that was found. On
592 * failure, return a negative error code.
593 */
594 int
uds_lookup(struct udssock * uds,const struct sockaddr * addr,socklen_t addr_len,endpoint_t user_endpt,struct udssock ** peerp)595 uds_lookup(struct udssock * uds, const struct sockaddr * addr,
596 socklen_t addr_len, endpoint_t user_endpt, struct udssock ** peerp)
597 {
598 struct udssock *peer;
599 const char *path;
600 size_t len;
601 dev_t dev;
602 ino_t ino;
603 int r;
604
605 /* Verify that the user gave us an acceptable address. */
606 if ((r = uds_check_addr(addr, addr_len, &path)) < 0)
607 return r;
608 len = (size_t)r;
609
610 /* Attempt to look up the socket file on the file system. */
611 r = socketpath(user_endpt, path, len, SPATH_CHECK, &dev, &ino);
612 if (r != OK)
613 return r;
614 assert(dev != NO_DEV && ino != 0);
615
616 if ((peer = udshash_get(dev, ino)) == NULL)
617 return ECONNREFUSED;
618 if (uds_get_type(peer) != uds_get_type(uds))
619 return EPROTOTYPE;
620
621 *peerp = peer;
622 return OK;
623 }
624
625 /*
626 * Given the listening socket 'uds', and the socket 'link' that is calling or
627 * has called connect(2) and is or will be linked to the listening socket's
628 * queue, create a new socket and connect it to 'link', putting both sockets in
629 * the connected state. The given link socket may be in unconnected,
630 * connecting, or disconnected state prior to the call. Return OK or an error
631 * code. The link state of the link socket remains unchanged in any case.
632 */
633 static int
uds_attach(struct udssock * uds,struct udssock * link)634 uds_attach(struct udssock * uds, struct udssock * link)
635 {
636 struct udssock *conn;
637 int r;
638
639 /*
640 * Allocate a new socket to use as peer socket for the connection that
641 * is about to be established. The new socket is not yet known by
642 * libsockevent.
643 */
644 if ((r = uds_alloc(&conn)) != OK)
645 return r;
646
647 /*
648 * Ask libsockevent to clone the sock object in the new UDS socket from
649 * the listening socket. This adds the sock object to libsockevent's
650 * data structures and ensures that we can safely use the socket
651 * despite the fact that it has not yet been accepted (and thus
652 * returned to libsockevent). From this moment on, we must either
653 * return the socket's ID (but not a pointer to it!) from uds_accept()
654 * or raise SEV_CLOSE on it.
655 */
656 sockevent_clone(&uds->uds_sock, &conn->uds_sock, uds_get_id(conn));
657
658 /* Connect the link socket to the new socket. */
659 link->uds_conn = conn;
660 link->uds_flags |= UDSF_CONNECTED;
661
662 /*
663 * Connect the new socket to the link socket as well. The child
664 * socket should also inherit pretty much all settings from the
665 * listening socket, including the bind path and the listening socket's
666 * bind-time credentials.
667 */
668 conn->uds_conn = link;
669 conn->uds_flags = uds->uds_flags & (UDSF_PASSCRED | UDSF_CONNWAIT);
670 conn->uds_flags |= UDSF_CONNECTED;
671 conn->uds_pathlen = uds->uds_pathlen;
672 memcpy(conn->uds_path, uds->uds_path, (size_t)uds->uds_pathlen);
673 memcpy(&conn->uds_cred, &uds->uds_cred, sizeof(conn->uds_cred));
674
675 return OK;
676 }
677
678 /*
679 * Connect a socket to a remote address.
680 */
681 static int
uds_connect(struct sock * sock,const struct sockaddr * addr,socklen_t addr_len,endpoint_t user_endpt)682 uds_connect(struct sock * sock, const struct sockaddr * addr,
683 socklen_t addr_len, endpoint_t user_endpt)
684 {
685 struct udssock *uds = (struct udssock *)sock;
686 struct udssock *link;
687 int r;
688
689 dprintf(("UDS: connect(%d)\n", uds_get_id(uds)));
690
691 /* For connection-oriented sockets, several state checks apply. */
692 if (uds_get_type(uds) != SOCK_DGRAM) {
693 if (uds_is_listening(uds))
694 return EOPNOTSUPP;
695 if (uds_is_connecting(uds))
696 return EALREADY;
697 if (uds_is_connected(uds))
698 return EISCONN;
699 /* Disconnected sockets may be reconnected, see below. */
700 } else {
701 /*
702 * Connectionless sockets may be unconnected by providing an
703 * address with family AF_UNSPEC. Handle this case first here.
704 */
705 if (addr_len >= offsetof(struct sockaddr, sa_data) &&
706 addr->sa_family == AF_UNSPEC) {
707 /*
708 * Reset this socket's previous connection to another
709 * socket, if any. Unconnecting has no effect on other
710 * sockets connected to this socket, though.
711 */
712 if (uds_has_link(uds))
713 uds_del_queue(uds->uds_link, uds);
714
715 return OK;
716 }
717 }
718
719 /*
720 * Find the socket identified by the given address. If it exists at
721 * all, see if it is a proper match.
722 */
723 if ((r = uds_lookup(uds, addr, addr_len, user_endpt, &link)) != OK)
724 return r;
725
726 /*
727 * Handle connectionless sockets first, in which case a connect links
728 * the socket to a send target and limits receipt to datagrams from
729 * that target. We actually point the socket to the peer socket,
730 * through uds_link. That also means that if the target socket
731 * disappears, we have to reset any sockets connected to it, in which
732 * case we return them to the unconnected state. In order to allow
733 * finding all sockets connected to a particular socket, we put all
734 * those sockets on their target's queue, hence why we use uds_link and
735 * not uds_conn. As mentioned before, we allow reconnecting without
736 * restrictions.
737 * TODO: see if reconnecting should clear a pending ECONNRESET.
738 *
739 * An important note: 'uds' and 'link' may actually be the same socket,
740 * if the caller chooses to connect a socket with itself!
741 */
742 if (uds_get_type(uds) == SOCK_DGRAM) {
743 /* Reconnecting to the same socket has no effect. */
744 if (uds_has_link(uds) && uds->uds_link == link)
745 return OK;
746
747 /*
748 * If the intended target is linked to another socket, we
749 * refuse linking to it. Sending or receiving would never work
750 * anyway. Do allow a socket to link to itself after being
751 * linked to another socket. The error code is the same as in
752 * the sending code, borrowed from Linux.
753 */
754 if (uds != link && uds_has_link(link) && link->uds_link != uds)
755 return EPERM;
756
757 /*
758 * Reset this socket's previous link to another socket, if any.
759 */
760 if (uds_has_link(uds))
761 uds_del_queue(uds->uds_link, uds);
762
763 /*
764 * Reset any links to this socket, except for the one by
765 * the intended target. Sending or receiving would no longer
766 * work anyway. If the socket was linked to itself, clear its
767 * self-link without generating an ECONNRESET. If the socket
768 * is relinking to itself, reestablish the link after first
769 * clearing it.
770 */
771 uds_clear_queue(uds, (uds != link) ? link : NULL);
772
773 uds_add_queue(link, uds);
774
775 return OK;
776 }
777
778 /*
779 * For connection-oriented sockets there is more to do. First, make
780 * sure that the peer is a listening socket, that it has not been shut
781 * down, and that its backlog is not already at the configured maximum.
782 */
783 if (!uds_is_listening(link))
784 return ECONNREFUSED;
785
786 if (uds_is_shutdown(link, SFL_SHUT_RD | SFL_SHUT_WR))
787 return ECONNREFUSED;
788
789 if (link->uds_queued >= link->uds_backlog)
790 return ECONNREFUSED;
791
792 /*
793 * The behavior of connect(2) now depends on whether LOCAL_CONNWAIT is
794 * set on either the connecting or the listening socket. If it is not,
795 * the socket will be connected to a new as-yet invisible socket, which
796 * will be the one returned from accept(2) later. If it was, the
797 * socket will be put in the connecting state.
798 */
799 if (!((uds->uds_flags | link->uds_flags) & UDSF_CONNWAIT)) {
800 if ((r = uds_attach(link, uds)) != OK)
801 return r;
802
803 assert(uds_is_connected(uds));
804 } else {
805 /*
806 * Disconnected sockets now stop being connected. Any pending
807 * data can still be received, though.
808 */
809 uds->uds_flags &= ~UDSF_CONNECTED;
810
811 r = SUSPEND;
812 }
813
814 /* Obtain credentials for the socket. */
815 uds_get_cred(uds, user_endpt);
816
817 /* Add the socket at the end of the listening socket's queue. */
818 uds_add_queue(link, uds);
819
820 assert(r != SUSPEND || uds_is_connecting(uds));
821
822 /*
823 * Let an accept call handle the rest, which will in turn resume this
824 * connect call. The sockevent library ensures that this works even if
825 * the call is non-blocking.
826 */
827 sockevent_raise(&link->uds_sock, SEV_ACCEPT);
828
829 return r;
830 }
831
832 /*
833 * Put a socket in listening mode.
834 */
835 static int
uds_listen(struct sock * sock,int backlog)836 uds_listen(struct sock * sock, int backlog)
837 {
838 struct udssock *uds = (struct udssock *)sock;
839
840 /* The maximum backlog value must not exceed its field size. */
841 assert(SOMAXCONN <= USHRT_MAX);
842
843 dprintf(("UDS: listen(%d)\n", uds_get_id(uds)));
844
845 /* Only connection-oriented types may be put in listening mode. */
846 if (uds_get_type(uds) == SOCK_DGRAM)
847 return EOPNOTSUPP;
848
849 /* A connecting or connected socket may not listen. */
850 if (uds_is_connecting(uds) || uds_is_connected(uds))
851 return EINVAL;
852
853 /* POSIX says that this is now the appropriate error code here. */
854 if (!uds_is_bound(uds))
855 return EDESTADDRREQ;
856
857 /*
858 * The socket is now entering the listening state. If it was
859 * previously disconnected, clear the connection flag.
860 */
861 uds->uds_flags &= ~UDSF_CONNECTED;
862
863 /*
864 * We do not remove sockets from the backlog if it is now being dropped
865 * below the current number of queued sockets. We only refuse newly
866 * connecting sockets beyond the backlog size.
867 */
868 uds->uds_backlog = backlog;
869
870 return OK;
871 }
872
873 /*
874 * Test whether an accept request would block. Return OK if a socket could be
875 * accepted, an appropriate error code if an accept call would fail instantly,
876 * or SUSPEND if the accept request would block waiting for a connection.
877 */
878 static int
uds_test_accept(struct sock * sock)879 uds_test_accept(struct sock * sock)
880 {
881 struct udssock *uds = (struct udssock *)sock;
882
883 /*
884 * Ensure that the socket is in listening mode. If not, we must return
885 * the error code that is appropriate for this socket type.
886 */
887 if (uds_get_type(uds) == SOCK_DGRAM)
888 return EOPNOTSUPP;
889 if (!uds_is_listening(uds))
890 return EINVAL;
891
892 /*
893 * If the socket has been shut down, new connections are no longer
894 * accepted and accept calls no longer block. This is not a POSIX
895 * requirement, but rather an application convenience feature.
896 */
897 if (uds->uds_queued == 0) {
898 if (uds_is_shutdown(uds, SFL_SHUT_RD | SFL_SHUT_WR))
899 return ECONNABORTED;
900
901 return SUSPEND;
902 }
903
904 return OK;
905 }
906
907 /*
908 * Accept a connection on a listening socket, creating a new socket. On
909 * success, return the new socket identifier, with the new socket stored in
910 * 'newsockp'. Otherwise, return an error code.
911 */
912 static sockid_t
uds_accept(struct sock * sock,struct sockaddr * addr,socklen_t * addr_len,endpoint_t user_endpt __unused,struct sock ** newsockp)913 uds_accept(struct sock * sock, struct sockaddr * addr, socklen_t * addr_len,
914 endpoint_t user_endpt __unused, struct sock ** newsockp)
915 {
916 struct udssock *uds = (struct udssock *)sock;
917 struct udssock *link, *conn;
918 sockid_t r;
919
920 dprintf(("UDS: accept(%d)\n", uds_get_id(uds)));
921
922 if ((r = uds_test_accept(sock)) != OK)
923 return r;
924
925 /*
926 * Take the first connecting socket off the listening queue.
927 */
928 assert(!TAILQ_EMPTY(&uds->uds_queue));
929
930 link = TAILQ_FIRST(&uds->uds_queue);
931
932 /*
933 * Depending on the LOCAL_CONNWAIT setting at the time of connect(2),
934 * the socket may be connecting or connected. In the latter case, its
935 * attached socket is the socket we will return now. Otherwise we have
936 * to attach a socket first.
937 */
938 assert(uds_is_connecting(link) || uds_is_connected(link));
939
940 if (uds_is_connecting(link)) {
941 /*
942 * Attach a new socket. If this fails, return the error but
943 * leave the connecting socket on the listening queue.
944 */
945 if ((r = uds_attach(uds, link)) != OK)
946 return r;
947
948 assert(uds_is_connected(link));
949
950 /*
951 * Wake up blocked (connect, send, select) calls on the peer
952 * socket.
953 */
954 sockevent_raise(&link->uds_sock, SEV_CONNECT);
955 }
956
957 uds_del_queue(uds, link);
958
959 /* Return the peer socket's address to the caller. */
960 uds_make_addr(link->uds_path, link->uds_pathlen, addr, addr_len);
961
962 conn = link->uds_conn;
963
964 dprintf(("UDS: accept returns %d\n", uds_get_id(conn)));
965
966 /*
967 * We already cloned the sock object, so return its ID but not a
968 * pointer to it. That tells libsockevent not to reinitialize it.
969 */
970 *newsockp = NULL;
971 return uds_get_id(conn);
972 }
973
974 /*
975 * Set socket options.
976 */
977 static int
uds_setsockopt(struct sock * sock,int level,int name,const struct sockdriver_data * data,socklen_t len)978 uds_setsockopt(struct sock * sock, int level, int name,
979 const struct sockdriver_data * data, socklen_t len)
980 {
981 struct udssock *uds = (struct udssock *)sock;
982 int r, val;
983
984 dprintf(("UDS: setsockopt(%d,%d,%d)\n", uds_get_id(uds), level, name));
985
986 switch (level) {
987 case SOL_SOCKET:
988 switch (name) {
989 case SO_SNDBUF:
990 case SO_RCVBUF:
991 /*
992 * The send buffer size may not be changed because the
993 * buffer is the same as the other side's receive
994 * buffer, and what the other side is may vary from
995 * send call to send call. Changing the receive buffer
996 * size would disallow us from even accurately guessing
997 * the send buffer size in getsockopt calls. Therefore
998 * both are hardcoded and cannot actually be changed.
999 * In order to support applications that want at least
1000 * a certain minimum, we do accept requests to shrink
1001 * either buffer, but we ignore the given size.
1002 */
1003 if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
1004 len)) != OK)
1005 return r;
1006
1007 if (val <= 0 || (size_t)val > uds_io_buflen())
1008 return EINVAL;
1009
1010 return OK; /* ignore new value */
1011 }
1012
1013 break;
1014
1015 case UDSPROTO_UDS:
1016 switch (name) {
1017 case LOCAL_CREDS:
1018 if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
1019 len)) != OK)
1020 return r;
1021
1022 if (val)
1023 uds->uds_flags |= UDSF_PASSCRED;
1024 else
1025 uds->uds_flags &= ~UDSF_PASSCRED;
1026
1027 /*
1028 * In incredibly rare cases, disabling this flag may
1029 * allow blocked sends to be resumed, because suddenly
1030 * no room for the credentials is needed in the receive
1031 * buffer anymore.
1032 */
1033 if (!val)
1034 sockevent_raise(&uds->uds_sock, SEV_SEND);
1035
1036 return OK;
1037
1038 case LOCAL_CONNWAIT:
1039 if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
1040 len)) != OK)
1041 return r;
1042
1043 if (val)
1044 uds->uds_flags |= UDSF_CONNWAIT;
1045 else
1046 uds->uds_flags &= ~UDSF_CONNWAIT;
1047
1048 /*
1049 * Changing the setting does not affect sockets that
1050 * are currently pending to be accepted. Therefore,
1051 * uds_accept() may have to deal with either case on a
1052 * socket-by-socket basis.
1053 */
1054 return OK;
1055
1056 case LOCAL_PEEREID:
1057 /* This option may be retrieved but not set. */
1058 return ENOPROTOOPT;
1059 }
1060
1061 break;
1062 }
1063
1064 return ENOPROTOOPT;
1065 }
1066
1067 /*
1068 * Retrieve socket options.
1069 */
1070 static int
uds_getsockopt(struct sock * sock,int level,int name,const struct sockdriver_data * data,socklen_t * len)1071 uds_getsockopt(struct sock * sock, int level, int name,
1072 const struct sockdriver_data * data, socklen_t * len)
1073 {
1074 struct udssock *uds = (struct udssock *)sock;
1075 int val;
1076
1077 dprintf(("UDS: getsockopt(%d,%d,%d)\n", uds_get_id(uds), level, name));
1078
1079 switch (level) {
1080 case SOL_SOCKET:
1081 switch (name) {
1082 case SO_SNDBUF:
1083 case SO_RCVBUF:
1084 /* See uds_setsockopt() for why this is static. */
1085 val = (int)uds_io_buflen();
1086
1087 return sockdriver_copyout_opt(data, &val, sizeof(val),
1088 len);
1089 }
1090
1091 break;
1092
1093 case UDSPROTO_UDS:
1094 switch (name) {
1095 case LOCAL_CREDS:
1096 val = !!(uds->uds_flags & UDSF_PASSCRED);
1097
1098 return sockdriver_copyout_opt(data, &val, sizeof(val),
1099 len);
1100
1101 case LOCAL_CONNWAIT:
1102 val = !!(uds->uds_flags & UDSF_CONNWAIT);
1103
1104 return sockdriver_copyout_opt(data, &val, sizeof(val),
1105 len);
1106
1107 case LOCAL_PEEREID:
1108 /* getpeereid(3) documents these error codes. */
1109 if (uds_get_type(uds) == SOCK_DGRAM)
1110 return EINVAL;
1111 if (!uds_is_connected(uds))
1112 return ENOTCONN;
1113
1114 /*
1115 * This is a custom MINIX3 error, indicating that there
1116 * are no credentials to return. This could be due to
1117 * a failure to obtain them (which *should* not happen)
1118 * but also if the socket was bound while connected,
1119 * disconnected, and then reused as listening socket.
1120 */
1121 if (uds->uds_conn->uds_cred.unp_pid == -1)
1122 return EINVAL;
1123
1124 return sockdriver_copyout_opt(data,
1125 &uds->uds_conn->uds_cred,
1126 sizeof(uds->uds_conn->uds_cred), len);
1127 }
1128
1129 break;
1130 }
1131
1132 return ENOPROTOOPT;
1133 }
1134
1135 /*
1136 * Retrieve a socket's local address.
1137 */
1138 static int
uds_getsockname(struct sock * sock,struct sockaddr * addr,socklen_t * addr_len)1139 uds_getsockname(struct sock * sock, struct sockaddr * addr,
1140 socklen_t * addr_len)
1141 {
1142 struct udssock *uds = (struct udssock *)sock;
1143
1144 dprintf(("UDS: getsockname(%d)\n", uds_get_id(uds)));
1145
1146 uds_make_addr(uds->uds_path, uds->uds_pathlen, addr, addr_len);
1147
1148 return OK;
1149 }
1150
1151 /*
1152 * Retrieve a socket's remote address.
1153 */
1154 static int
uds_getpeername(struct sock * sock,struct sockaddr * addr,socklen_t * addr_len)1155 uds_getpeername(struct sock * sock, struct sockaddr * addr,
1156 socklen_t * addr_len)
1157 {
1158 struct udssock *uds = (struct udssock *)sock;
1159 struct udssock *peer;
1160
1161 dprintf(("UDS: getpeername(%d)\n", uds_get_id(uds)));
1162
1163 /*
1164 * For disconnected sockets, we no longer have a peer socket and thus
1165 * also no peer address. Too bad, but NetBSD does the same.
1166 *
1167 * For connecting sockets we could in fact return a peer address, but
1168 * POSIX says (and other platforms agree) that we should deny the call.
1169 */
1170 peer = uds_get_peer(uds);
1171
1172 if (peer == NULL || uds_is_connecting(uds))
1173 return ENOTCONN;
1174
1175 uds_make_addr(peer->uds_path, peer->uds_pathlen, addr, addr_len);
1176
1177 return OK;
1178 }
1179
1180 /*
1181 * Shut down socket send and receive operations. Note that 'flags' is a
1182 * bitwise mask with libsockevent's SFL_SHUT_{RD,WR} flags rather than the set
1183 * of SHUT_{RD,WR,RDWR} values from userland.
1184 */
1185 static int
uds_shutdown(struct sock * sock,unsigned int flags)1186 uds_shutdown(struct sock * sock, unsigned int flags)
1187 {
1188 struct udssock *uds = (struct udssock *)sock;
1189 struct udssock *conn;
1190 unsigned int mask;
1191
1192 dprintf(("UDS: shutdown(%d,0x%x)\n", uds_get_id(uds), flags));
1193
1194 /*
1195 * If we are shutting down the socket for reading, we can already close
1196 * any in-flight file descriptors associated with this socket.
1197 */
1198 if (flags & SFL_SHUT_RD)
1199 uds_io_reset(uds);
1200
1201 /*
1202 * A shutdown on this side of a connection may have an effect on
1203 * ongoing operations on the other side. Fire appropriate events.
1204 */
1205 if (uds_is_connected(uds)) {
1206 assert(uds_get_type(uds) != SOCK_DGRAM);
1207
1208 conn = uds->uds_conn;
1209
1210 mask = 0;
1211 if (flags & SFL_SHUT_RD)
1212 mask |= SEV_SEND;
1213 if (flags & SFL_SHUT_WR)
1214 mask |= SEV_RECV;
1215
1216 sockevent_raise(&conn->uds_sock, mask);
1217 }
1218
1219 return OK;
1220 }
1221
1222 /*
1223 * Close a socket.
1224 *
1225 * The 'force' flag is unused because we need never wait for data to be sent,
1226 * since we keep all in-flight data on the receiver side.
1227 */
1228 static int
uds_close(struct sock * sock,int force __unused)1229 uds_close(struct sock * sock, int force __unused)
1230 {
1231 struct udssock *uds = (struct udssock *)sock;
1232
1233 dprintf(("UDS: close(%d)\n", uds_get_id(uds)));
1234
1235 if (uds_get_type(uds) == SOCK_DGRAM) {
1236 /* If this socket is linked to a target, disconnect it. */
1237 if (uds_has_link(uds))
1238 uds_del_queue(uds->uds_link, uds);
1239
1240 /* Reset all sockets linked to this socket as a target. */
1241 uds_clear_queue(uds, NULL);
1242 } else if (uds_is_listening(uds)) {
1243 /*
1244 * Abort all connecting sockets queued on this socket, and
1245 * break all connections for connected sockets queued on this
1246 * socket, freeing their peers.
1247 */
1248 uds_clear_queue(uds, NULL);
1249 } else if (uds_has_link(uds)) {
1250 /*
1251 * This socket is connecting or connected while the other side
1252 * has not been accepted yet. Remove the socket from the
1253 * listening socket's queue, and if it was connected, get rid
1254 * of its peer socket altogether.
1255 */
1256 assert(uds_is_listening(uds->uds_link));
1257
1258 uds_del_queue(uds->uds_link, uds);
1259
1260 if (uds_is_connected(uds))
1261 uds_disconnect(uds, TRUE /*was_linked*/);
1262 } else if (uds_is_connected(uds)) {
1263 /*
1264 * Decouple the peer socket from this socket, and possibly wake
1265 * up any pending operations on it. The socket remains marked
1266 * as connected, but will now be disconnected.
1267 */
1268 uds_disconnect(uds, FALSE /*was_linked*/);
1269 }
1270
1271 if (uds_is_hashed(uds))
1272 udshash_del(uds);
1273
1274 return OK;
1275 }
1276
1277 static const struct sockevent_ops uds_ops = {
1278 .sop_pair = uds_pair,
1279 .sop_bind = uds_bind,
1280 .sop_connect = uds_connect,
1281 .sop_listen = uds_listen,
1282 .sop_accept = uds_accept,
1283 .sop_test_accept = uds_test_accept,
1284 .sop_pre_send = uds_pre_send,
1285 .sop_send = uds_send,
1286 .sop_test_send = uds_test_send,
1287 .sop_pre_recv = uds_pre_recv,
1288 .sop_recv = uds_recv,
1289 .sop_test_recv = uds_test_recv,
1290 .sop_setsockopt = uds_setsockopt,
1291 .sop_getsockopt = uds_getsockopt,
1292 .sop_getsockname = uds_getsockname,
1293 .sop_getpeername = uds_getpeername,
1294 .sop_shutdown = uds_shutdown,
1295 .sop_close = uds_close,
1296 .sop_free = uds_free
1297 };
1298
1299 /*
1300 * Initialize the service.
1301 */
1302 static int
uds_init(int type __unused,sef_init_info_t * info __unused)1303 uds_init(int type __unused, sef_init_info_t * info __unused)
1304 {
1305 unsigned int i;
1306
1307 /* Initialize the list of free sockets. */
1308 TAILQ_INIT(&uds_freelist);
1309
1310 for (i = 0; i < __arraycount(uds_array); i++) {
1311 uds_array[i].uds_flags = 0;
1312
1313 TAILQ_INSERT_TAIL(&uds_freelist, &uds_array[i], uds_next);
1314 }
1315
1316 /* Initialize the file-to-socket hash table. */
1317 udshash_init();
1318
1319 /* Initialize the input/output module. */
1320 uds_io_init();
1321
1322 /* Initialize the status module. */
1323 uds_stat_init();
1324
1325 /* Initialize the sockevent library. */
1326 sockevent_init(uds_socket);
1327
1328 uds_in_use = 0;
1329 uds_running = TRUE;
1330
1331 return OK;
1332 }
1333
1334 /*
1335 * Clean up before shutdown.
1336 */
1337 static void
uds_cleanup(void)1338 uds_cleanup(void)
1339 {
1340
1341 /* Tell the status module to clean up. */
1342 uds_stat_cleanup();
1343 }
1344
1345 /*
1346 * The service has received a signal.
1347 */
1348 static void
uds_signal(int signo)1349 uds_signal(int signo)
1350 {
1351
1352 /* Only check for the termination signal. Ignore anything else. */
1353 if (signo != SIGTERM)
1354 return;
1355
1356 /* Exit only once all sockets have been closed. */
1357 uds_running = FALSE;
1358
1359 if (uds_in_use == 0)
1360 sef_cancel();
1361 }
1362
1363 /*
1364 * Perform initialization using the System Event Framework (SEF).
1365 */
1366 static void
uds_startup(void)1367 uds_startup(void)
1368 {
1369
1370 /* Register initialization callbacks. */
1371 sef_setcb_init_fresh(uds_init);
1372
1373 /* Register signal callback. */
1374 sef_setcb_signal_handler(uds_signal);
1375
1376 /* Let SEF perform startup. */
1377 sef_startup();
1378 }
1379
1380 /*
1381 * The UNIX Domain Sockets driver.
1382 */
1383 int
main(void)1384 main(void)
1385 {
1386 message m;
1387 int r, ipc_status;
1388
1389 /* Initialize the service. */
1390 uds_startup();
1391
1392 /* Loop receiving and processing messages until instructed to stop. */
1393 while (uds_running || uds_in_use > 0) {
1394 if ((r = sef_receive_status(ANY, &m, &ipc_status)) != OK) {
1395 if (r == EINTR)
1396 continue; /* sef_cancel() was called */
1397
1398 panic("UDS: sef_receive_status failed: %d", r);
1399 }
1400
1401 /*
1402 * Messages from the MIB service are (ultimately) for the
1403 * status module. Everything else is assumed to be a socket
1404 * request and passed to libsockevent, which will ignore
1405 * anything it does not recognize.
1406 */
1407 if (m.m_source == MIB_PROC_NR)
1408 rmib_process(&m, ipc_status);
1409 else
1410 sockevent_process(&m, ipc_status);
1411 }
1412
1413 /* Clean up before graceful shutdown. */
1414 uds_cleanup();
1415
1416 return EXIT_SUCCESS;
1417 }
1418