1 /* $NetBSD: sys_epoll.c,v 1.6 2026/10/22 20:48:20 andvar Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2007 Roman Divacky 7 * Copyright (c) 2014 Dmitry Chagin <dchagin (at) FreeBSD.org> 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: sys_epoll.c,v 1.6 2026/10/22 20:48:20 andvar Exp $"); 32 33 34 #include <sys/param.h> 35 #include <sys/types.h> 36 #include <sys/bitops.h> 37 #include <sys/epoll.h> 38 #include <sys/event.h> 39 #include <sys/eventvar.h> 40 #include <sys/errno.h> 41 #include <sys/file.h> 42 #include <sys/filedesc.h> 43 #include <sys/fcntl.h> 44 #include <sys/proc.h> 45 #include <sys/signal.h> 46 #include <sys/vnode.h> 47 48 #include <sys/syscallargs.h> 49 50 #define EPOLL_MAX_DEPTH 5 51 52 #define EPOLL_EVRD (EPOLLIN|EPOLLRDNORM) 53 #define EPOLL_EVWR (EPOLLOUT|EPOLLWRNORM) 54 #define EPOLL_EVSUP (EPOLLET|EPOLLONESHOT|EPOLLHUP|EPOLLERR|EPOLLPRI \ 55 |EPOLL_EVRD|EPOLL_EVWR|EPOLLRDHUP) 56 57 #define kext_data ext[0] 58 #define kext_epfd ext[1] 59 #define kext_fd ext[2] 60 61 #if DEBUG 62 #define DPRINTF(x) uprintf x 63 #else 64 #define DPRINTF(x) __nothing 65 #endif 66 67 struct epoll_edge { 68 int epfd; 69 int fd; 70 }; 71 72 __BITMAP_TYPE(epoll_seen, char, 1); 73 74 static int epoll_to_kevent(int, int, struct epoll_event *, struct kevent *, 75 int *); 76 static void kevent_to_epoll(struct kevent *, struct epoll_event *); 77 static int epoll_kev_put_events(void *, struct kevent *, struct kevent *, 78 size_t, int); 79 static int epoll_kev_fetch_changes(void *, const struct kevent *, 80 struct kevent *, size_t, int); 81 static int epoll_kev_fetch_timeout(const void *, void *, size_t); 82 static int epoll_register_kevent(register_t *, int, int, int, 83 unsigned int); 84 static int epoll_fd_registered(register_t *, int, int); 85 static int epoll_delete_all_events(register_t *, int, int); 86 static int epoll_recover_watch_tree(struct epoll_edge *, size_t, size_t); 87 static int epoll_dfs(struct epoll_edge *, size_t, struct epoll_seen *, 88 size_t, int, int); 89 static int epoll_check_loop_and_depth(struct lwp *, int, int); 90 91 /* 92 * epoll_create1(2). Parse the flags and then create a kqueue instance. 93 */ 94 int 95 sys_epoll_create1(struct lwp *l, const struct sys_epoll_create1_args *uap, 96 register_t *retval) 97 { 98 /* { 99 syscallarg(int) flags; 100 } */ 101 struct sys_kqueue1_args kqa; 102 103 if ((SCARG(uap, flags) & ~(EPOLL_CLOEXEC)) != 0) 104 return EINVAL; 105 106 memset(&kqa, 0, sizeof(kqa)); 107 SCARG(&kqa, flags) = 0; 108 if (SCARG(uap, flags) & EPOLL_CLOEXEC) 109 SCARG(&kqa, flags) |= O_CLOEXEC; 110 111 return sys_kqueue1(l, &kqa, retval); 112 } 113 114 /* 115 * Structure converting function from epoll to kevent. 116 */ 117 static int 118 epoll_to_kevent(int epfd, int fd, struct epoll_event *l_event, 119 struct kevent *kevent, int *nkevents) 120 { 121 uint32_t levents = l_event->events; 122 uint32_t kev_flags = EV_ADD | EV_ENABLE; 123 124 /* flags related to how event is registered */ 125 if ((levents & EPOLLONESHOT) != 0) 126 kev_flags |= EV_DISPATCH; 127 if ((levents & EPOLLET) != 0) 128 kev_flags |= EV_CLEAR; 129 if ((levents & EPOLLERR) != 0) 130 kev_flags |= EV_ERROR; 131 if ((levents & EPOLLRDHUP) != 0) 132 kev_flags |= EV_EOF; 133 134 /* flags related to what event is registered */ 135 if ((levents & EPOLL_EVRD) != 0) { 136 EV_SET(kevent, fd, EVFILT_READ, kev_flags, 0, 0, 0); 137 kevent->kext_data = l_event->data; 138 kevent->kext_epfd = epfd; 139 kevent->kext_fd = fd; 140 ++kevent; 141 ++(*nkevents); 142 } 143 if ((levents & EPOLL_EVWR) != 0) { 144 EV_SET(kevent, fd, EVFILT_WRITE, kev_flags, 0, 0, 0); 145 kevent->kext_data = l_event->data; 146 kevent->kext_epfd = epfd; 147 kevent->kext_fd = fd; 148 ++kevent; 149 ++(*nkevents); 150 } 151 /* zero event mask is legal */ 152 if ((levents & (EPOLL_EVRD | EPOLL_EVWR)) == 0) { 153 EV_SET(kevent++, fd, EVFILT_READ, EV_ADD|EV_DISABLE, 0, 0, 0); 154 ++(*nkevents); 155 } 156 157 if ((levents & ~(EPOLL_EVSUP)) != 0) { 158 return EINVAL; 159 } 160 161 return 0; 162 } 163 164 /* 165 * Structure converting function from kevent to epoll. In a case 166 * this is called on error in registration we store the error in 167 * event->data and pick it up later in sys_epoll_ctl(). 168 */ 169 static void 170 kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event) 171 { 172 173 l_event->data = kevent->kext_data; 174 175 if ((kevent->flags & EV_ERROR) != 0) { 176 l_event->events = EPOLLERR; 177 return; 178 } 179 180 /* XXX EPOLLPRI, EPOLLHUP */ 181 switch (kevent->filter) { 182 case EVFILT_READ: 183 l_event->events = EPOLLIN; 184 if ((kevent->flags & EV_EOF) != 0) 185 l_event->events |= EPOLLRDHUP; 186 break; 187 case EVFILT_WRITE: 188 l_event->events = EPOLLOUT; 189 break; 190 default: 191 DPRINTF(("%s: unhandled kevent filter %d\n", __func__, 192 kevent->filter)); 193 break; 194 } 195 } 196 197 /* 198 * Copyout callback used by kevent. This converts kevent events to 199 * epoll events that are located in args->eventlist. 200 */ 201 static int 202 epoll_kev_put_events(void *ctx, struct kevent *events, 203 struct kevent *eventlist, size_t index, int n) 204 { 205 int i; 206 struct epoll_event *eep = (struct epoll_event *)eventlist; 207 208 KASSERT(n >= 0 && n < EPOLL_MAX_EVENTS); 209 210 for (i = 0; i < n; i++) 211 kevent_to_epoll(events + i, eep + index + i); 212 213 return 0; 214 } 215 216 /* 217 * Copyin callback used by kevent. This copies already 218 * converted filters from kernel memory to the kevent 219 * internal kernel memory. Hence the memcpy instead of 220 * copyin. 221 */ 222 static int 223 epoll_kev_fetch_changes(void *ctx, const struct kevent *changelist, 224 struct kevent *changes, size_t index, int n) 225 { 226 KASSERT(n >= 0 && n < EPOLL_MAX_EVENTS); 227 228 memcpy(changes, changelist + index, n * sizeof(*changes)); 229 230 return 0; 231 } 232 233 /* 234 * Timer copy callback used by kevent. Copies a converted timeout 235 * from kernel memory to kevent memory. Hence the memcpy instead of 236 * just using copyin. 237 */ 238 static int 239 epoll_kev_fetch_timeout(const void *src, void *dest, size_t size) 240 { 241 memcpy(dest, src, size); 242 243 return 0; 244 } 245 246 /* 247 * Load epoll filter, convert it to kevent filter and load it into 248 * kevent subsystem. 249 * 250 * event must point to kernel memory or be NULL. 251 */ 252 int 253 epoll_ctl_common(struct lwp *l, register_t *retval, int epfd, int op, int fd, 254 struct epoll_event *event) 255 { 256 struct kevent kev[2]; 257 struct kevent_ops k_ops = { 258 .keo_private = NULL, 259 .keo_fetch_timeout = NULL, 260 .keo_fetch_changes = epoll_kev_fetch_changes, 261 .keo_put_events = NULL, 262 }; 263 file_t *epfp, *fp; 264 int error = 0; 265 int nchanges = 0; 266 267 /* 268 * Need to validate epfd and fd separately from kevent1 to match 269 * Linux's errno behaviour. 270 */ 271 epfp = fd_getfile(epfd); 272 if (epfp == NULL) 273 return EBADF; 274 if (epfp->f_type != DTYPE_KQUEUE) 275 error = EINVAL; 276 fd_putfile(epfd); 277 if (error != 0) 278 return error; 279 280 fp = fd_getfile(fd); 281 if (fp == NULL) 282 return EBADF; 283 if (fp->f_type == DTYPE_VNODE) { 284 switch (fp->f_vnode->v_type) { 285 case VREG: 286 case VDIR: 287 case VBLK: 288 case VLNK: 289 error = EPERM; 290 break; 291 292 default: 293 break; 294 } 295 } 296 fd_putfile(fd); 297 if (error != 0) 298 return error; 299 300 /* Linux disallows spying on himself */ 301 if (epfd == fd) { 302 return EINVAL; 303 } 304 305 if (op != EPOLL_CTL_DEL) { 306 error = epoll_to_kevent(epfd, fd, event, kev, &nchanges); 307 if (error != 0) 308 return error; 309 } 310 311 switch (op) { 312 case EPOLL_CTL_MOD: 313 error = epoll_delete_all_events(retval, epfd, fd); 314 if (error != 0) 315 return error; 316 break; 317 318 case EPOLL_CTL_ADD: 319 if (epoll_fd_registered(retval, epfd, fd)) 320 return EEXIST; 321 error = epoll_check_loop_and_depth(l, epfd, fd); 322 if (error != 0) 323 return error; 324 break; 325 326 case EPOLL_CTL_DEL: 327 /* CTL_DEL means unregister this fd with this epoll */ 328 return epoll_delete_all_events(retval, epfd, fd); 329 330 default: 331 DPRINTF(("%s: invalid op %d\n", __func__, op)); 332 return EINVAL; 333 } 334 335 error = kevent1(retval, epfd, kev, nchanges, NULL, 0, NULL, &k_ops); 336 337 if (error == EOPNOTSUPP) { 338 error = EPERM; 339 } 340 341 return error; 342 } 343 344 /* 345 * epoll_ctl(2). Copyin event if necessary and then call 346 * epoll_ctl_common(). 347 */ 348 int 349 sys_epoll_ctl(struct lwp *l, const struct sys_epoll_ctl_args *uap, 350 register_t *retval) 351 { 352 /* { 353 syscallarg(int) epfd; 354 syscallarg(int) op; 355 syscallarg(int) fd; 356 syscallarg(struct epoll_event *) event; 357 } */ 358 struct epoll_event ee; 359 struct epoll_event *eep; 360 int error; 361 362 if (SCARG(uap, op) != EPOLL_CTL_DEL) { 363 error = copyin(SCARG(uap, event), &ee, sizeof(ee)); 364 if (error != 0) 365 return error; 366 367 eep = ⅇ 368 } else 369 eep = NULL; 370 371 return epoll_ctl_common(l, retval, SCARG(uap, epfd), SCARG(uap, op), 372 SCARG(uap, fd), eep); 373 } 374 375 /* 376 * Wait for a filter to be triggered on the epoll file descriptor. 377 * All of the epoll_*wait* syscalls eventually end up here. 378 * 379 * events, nss, and ssp must point to kernel memory (or be NULL). 380 */ 381 int 382 epoll_wait_common(struct lwp *l, register_t *retval, int epfd, 383 struct epoll_event *events, int maxevents, struct timespec *tsp, 384 const sigset_t *nssp) 385 { 386 struct kevent_ops k_ops = { 387 .keo_private = NULL, 388 .keo_fetch_timeout = epoll_kev_fetch_timeout, 389 .keo_fetch_changes = NULL, 390 .keo_put_events = epoll_kev_put_events, 391 }; 392 struct proc *p = l->l_proc; 393 file_t *epfp; 394 sigset_t oss; 395 int error = 0; 396 397 if (maxevents <= 0 || maxevents > EPOLL_MAX_EVENTS) 398 return EINVAL; 399 400 /* 401 * Need to validate epfd separately from kevent1 to match 402 * Linux's errno behaviour. 403 */ 404 epfp = fd_getfile(epfd); 405 if (epfp == NULL) 406 return EBADF; 407 if (epfp->f_type != DTYPE_KQUEUE) 408 error = EINVAL; 409 fd_putfile(epfd); 410 if (error != 0) 411 return error; 412 413 if (nssp != NULL) { 414 mutex_enter(p->p_lock); 415 error = sigprocmask1(l, SIG_SETMASK, nssp, &oss); 416 mutex_exit(p->p_lock); 417 if (error != 0) 418 return error; 419 } 420 421 error = kevent1(retval, epfd, NULL, 0, (struct kevent *)events, 422 maxevents, tsp, &k_ops); 423 /* 424 * Since we're not registering nay events, ENOMEM should not 425 * be possible for this specific kevent1 call. 426 */ 427 KASSERT(error != ENOMEM); 428 429 if (nssp != NULL) { 430 mutex_enter(p->p_lock); 431 error = sigprocmask1(l, SIG_SETMASK, &oss, NULL); 432 mutex_exit(p->p_lock); 433 } 434 435 return error; 436 } 437 438 /* 439 * epoll_pwait2(2). 440 */ 441 int 442 sys_epoll_pwait2(struct lwp *l, const struct sys_epoll_pwait2_args *uap, 443 register_t *retval) 444 { 445 /* { 446 syscallarg(int) epfd; 447 syscallarg(struct epoll_event *) events; 448 syscallarg(int) maxevents; 449 syscallarg(struct timespec *) timeout; 450 syscallarg(sigset_t *) sigmask; 451 } */ 452 struct epoll_event *events; 453 struct timespec ts, *tsp; 454 sigset_t ss, *ssp; 455 int error; 456 const int maxevents = SCARG(uap, maxevents); 457 458 if (maxevents <= 0 || maxevents >= EPOLL_MAX_EVENTS) 459 return EINVAL; 460 461 if (SCARG(uap, timeout) != NULL) { 462 error = copyin(SCARG(uap, timeout), &ts, sizeof(ts)); 463 if (error != 0) 464 return error; 465 466 tsp = &ts; 467 } else 468 tsp = NULL; 469 470 if (SCARG(uap, sigmask) != NULL) { 471 error = copyin(SCARG(uap, sigmask), &ss, sizeof(ss)); 472 if (error != 0) 473 return error; 474 475 ssp = &ss; 476 } else 477 ssp = NULL; 478 479 events = kmem_alloc(maxevents * sizeof(*events), KM_SLEEP); 480 481 error = epoll_wait_common(l, retval, SCARG(uap, epfd), events, 482 maxevents, tsp, ssp); 483 if (error == 0) 484 error = copyout(events, SCARG(uap, events), 485 *retval * sizeof(*events)); 486 487 kmem_free(events, maxevents * sizeof(*events)); 488 return error; 489 } 490 491 /* 492 * Helper that registers a single kevent. 493 */ 494 static int 495 epoll_register_kevent(register_t *retval, int epfd, int fd, int filter, 496 unsigned int flags) 497 { 498 struct kevent kev; 499 struct kevent_ops k_ops = { 500 .keo_private = NULL, 501 .keo_fetch_timeout = NULL, 502 .keo_fetch_changes = epoll_kev_fetch_changes, 503 .keo_put_events = NULL, 504 }; 505 506 EV_SET(&kev, fd, filter, flags, 0, 0, 0); 507 508 return kevent1(retval, epfd, &kev, 1, NULL, 0, NULL, &k_ops); 509 } 510 511 /* 512 * Check if an fd is already registered in the kqueue referenced by epfd. 513 */ 514 static int 515 epoll_fd_registered(register_t *retval, int epfd, int fd) 516 { 517 /* 518 * Set empty filter flags to avoid accidental modification of already 519 * registered events. In the case of event re-registration: 520 * 1. If event does not exists kevent() does nothing and returns ENOENT 521 * 2. If event does exists, it's enabled/disabled state is preserved 522 * but fflags, data and udata fields are overwritten. So we can not 523 * set socket lowats and store user's context pointer in udata. 524 */ 525 if (epoll_register_kevent(retval, epfd, fd, EVFILT_READ, 0) != ENOENT || 526 epoll_register_kevent(retval, epfd, fd, EVFILT_WRITE, 0) != ENOENT) 527 return 1; 528 529 return 0; 530 } 531 532 /* 533 * Remove all events in the kqueue referenced by epfd that depend on 534 * fd. 535 */ 536 static int 537 epoll_delete_all_events(register_t *retval, int epfd, int fd) 538 { 539 int error1, error2; 540 541 error1 = epoll_register_kevent(retval, epfd, fd, EVFILT_READ, 542 EV_DELETE); 543 error2 = epoll_register_kevent(retval, epfd, fd, EVFILT_WRITE, 544 EV_DELETE); 545 546 /* return 0 if at least one result positive */ 547 return error1 == 0 ? 0 : error2; 548 } 549 550 /* 551 * Iterate through all the knotes and recover a directed graph on 552 * which kqueues are watching each other. 553 * 554 * If edges is NULL, the number of edges is still counted but no graph 555 * is assembled. 556 */ 557 static int 558 epoll_recover_watch_tree(struct epoll_edge *edges, size_t nedges, size_t nfds) { 559 file_t *currfp, *targetfp; 560 struct knote *kn, *tmpkn; 561 size_t i, nedges_so_far = 0; 562 563 for (i = 0; i < nfds && (edges == NULL || nedges_so_far < nedges); i++) 564 { 565 currfp = fd_getfile(i); 566 if (currfp == NULL) 567 continue; 568 if (currfp->f_type != DTYPE_KQUEUE) 569 goto continue_count_outer; 570 571 SLIST_FOREACH_SAFE(kn, &currfp->f_kqueue->kq_sel.sel_klist, 572 kn_selnext, tmpkn) { 573 targetfp = fd_getfile(kn->kn_kevent.kext_epfd); 574 if (targetfp == NULL) 575 continue; 576 if (targetfp->f_type == DTYPE_KQUEUE) { 577 if (edges != NULL) { 578 edges[nedges_so_far].epfd = 579 kn->kn_kevent.kext_epfd; 580 edges[nedges_so_far].fd = 581 kn->kn_kevent.kext_fd; 582 } 583 nedges_so_far++; 584 } 585 586 fd_putfile(kn->kn_kevent.kext_epfd); 587 } 588 589 continue_count_outer: 590 fd_putfile(i); 591 } 592 593 return nedges_so_far; 594 } 595 596 /* 597 * Run dfs on the graph described by edges, checking for loops and a 598 * depth greater than EPOLL_MAX_DEPTH. 599 */ 600 static int 601 epoll_dfs(struct epoll_edge *edges, size_t nedges, struct epoll_seen *seen, 602 size_t nseen, int currfd, int depth) 603 { 604 int error; 605 size_t i; 606 607 KASSERT(edges != NULL); 608 KASSERT(seen != NULL); 609 KASSERT(nedges > 0); 610 KASSERT(currfd < nseen); 611 KASSERT(0 <= depth && depth <= EPOLL_MAX_DEPTH + 1); 612 613 if (__BITMAP_ISSET(currfd, seen)) 614 return ELOOP; 615 616 __BITMAP_SET(currfd, seen); 617 618 depth++; 619 if (depth > EPOLL_MAX_DEPTH) 620 return EINVAL; 621 622 for (i = 0; i < nedges; i++) { 623 if (edges[i].epfd != currfd) 624 continue; 625 626 error = epoll_dfs(edges, nedges, seen, nseen, 627 edges[i].fd, depth); 628 if (error != 0) 629 return error; 630 } 631 632 return 0; 633 } 634 635 /* 636 * Check if adding fd to epfd would violate the maximum depth or 637 * create a loop. 638 */ 639 static int 640 epoll_check_loop_and_depth(struct lwp *l, int epfd, int fd) 641 { 642 int error; 643 file_t *fp; 644 struct epoll_edge *edges; 645 struct epoll_seen *seen; 646 size_t nedges, nfds, seen_size; 647 bool fdirrelevant; 648 649 /* If the target isn't another kqueue, we can skip this check */ 650 fp = fd_getfile(fd); 651 if (fp == NULL) 652 return 0; 653 fdirrelevant = fp->f_type != DTYPE_KQUEUE; 654 fd_putfile(fd); 655 if (fdirrelevant) 656 return 0; 657 658 nfds = l->l_proc->p_fd->fd_lastfile + 1; 659 660 /* 661 * We call epoll_recover_watch_tree twice, once to find the 662 * number of edges, and once to actually fill them in. We add one 663 * because we want to include the edge epfd->fd. 664 */ 665 nedges = 1 + epoll_recover_watch_tree(NULL, 0, nfds); 666 667 edges = kmem_zalloc(nedges * sizeof(*edges), KM_SLEEP); 668 669 epoll_recover_watch_tree(edges + 1, nedges - 1, nfds); 670 671 edges[0].epfd = epfd; 672 edges[0].fd = fd; 673 674 seen_size = __BITMAP_SIZE(char, nfds); 675 seen = kmem_zalloc(seen_size, KM_SLEEP); 676 677 error = epoll_dfs(edges, nedges, seen, nfds, epfd, 0); 678 679 kmem_free(seen, seen_size); 680 kmem_free(edges, nedges * sizeof(*edges)); 681 682 return error; 683 } 684